for loop for pll + ddr_ctr_config
[keystone-rtos/ibl.git] / src / device / c66x / c66x.c
1 /*
2  *
3  * Copyright (C) 2010 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 */
38 /************************************************************************************
39  * FILE PURPOSE: C66x Device Specific functions
40  ************************************************************************************
41  * FILE NAME: c66x.c
42  *
43  * DESCRIPTION: Implements the device specific functions for the IBL
44  *
45  * @file c66x.c
46  *
47  * @brief
48  *  This file implements the device specific functions for the IBL
49  *
50  ************************************************************************************/
51 #include "ibl.h"
52 #include "iblloc.h"
53 #include "iblcfg.h"
54 #include "device.h"
55 #include "pllapi.h"
56 #include "emif31api.h"
57 #include "pscapi.h"
58 #include "gpio.h"
59 #include "qm_api.h"
60 #include "cpdma_api.h"
61 #include "pa_api.h"
62 #include "serdes_api.h"
63 #include "net.h"
64 #include "nandhwapi.h"
65 #include "nor_api.h"
66 #include "spi_api.h"
67 #include <string.h>
69 #define PLL_DDR_INIT_LOOPMAX 10
70 extern cregister unsigned int DNUM;
72 /**
73  *  @brief Determine if an address is local
74  *
75  *  @details
76  *    Examines an input address to determine if it is a local address. Using the largest
77  *    L2 size on the C6670.
78  */
79 bool address_is_local (Uint32 addr)
80 {
81     /* L2 */
82     if ((addr >= 0x00800000) && (addr < 0x00900000))
83         return (TRUE);
85     /* L1P */
86     if ((addr >= 0x00e00000) && (addr < 0x00e08000))
87         return (TRUE);
89     /* L2D */
90     if ((addr >= 0x00f00000) && (addr < 0x00f08000))
91         return (TRUE);
93     return (FALSE);
95 }
98 /**
99  * @brief  Convert a local l1d, l1p or l2 address to a global address
100  *
101  * @details
102  *  The global address is formed. If the address is not local then
103  *  the input address is returned
104  */
105 Uint32 deviceLocalAddrToGlobal (Uint32 addr)
108     if (address_is_local (addr))
109         addr = (1 << 28) | (DNUM << 24) | addr;
111     return (addr);
114         
115         
116 /**
117  * @brief
118  *   Enable the DDR
119  *
120  * @details
121  *   The DDR controller on the c66x is an emif 4.0. The controller is
122  *   initialized directly with the supplied values
123  */
124 void deviceDdrConfig (void)
126     uint32 loopcount=0;
127     /* The emif registers must be made visible. MPAX mapping 2 is used */
128     DEVICE_REG_XMPAX_L(2) =  0x10000000 | 0xff;     /* replacement addr + perm*/
129     DEVICE_REG_XMPAX_H(2) =  0x2100000B;         /* base addr + seg size (64KB)*/       
130     
131     for (loopcount = 0; loopcount < PLL_DDR_INIT_LOOPMAX ; loopcount++)
132     {
133         /* Calling MAIN, PA, DDR PLL init before DDR controller init */
134         if (ibl.pllConfig[ibl_MAIN_PLL].doEnable == TRUE)
135                 hwPllSetPll (MAIN_PLL, 
136                              ibl.pllConfig[ibl_MAIN_PLL].prediv,
137                              ibl.pllConfig[ibl_MAIN_PLL].mult,
138                              ibl.pllConfig[ibl_MAIN_PLL].postdiv);
140         if (ibl.pllConfig[ibl_NET_PLL].doEnable == TRUE)
141             hwPllSetCfgPll (DEVICE_PLL_BASE(NET_PLL),
142                             ibl.pllConfig[ibl_NET_PLL].prediv,
143                             ibl.pllConfig[ibl_NET_PLL].mult,
144                             ibl.pllConfig[ibl_NET_PLL].postdiv,
145                             ibl.pllConfig[ibl_MAIN_PLL].pllOutFreqMhz,
146                             ibl.pllConfig[ibl_NET_PLL].pllOutFreqMhz);
148         if (ibl.pllConfig[ibl_DDR_PLL].doEnable == TRUE)
149             hwPllSetCfg2Pll (DEVICE_PLL_BASE(DDR_PLL),
150                              ibl.pllConfig[ibl_DDR_PLL].prediv,
151                              ibl.pllConfig[ibl_DDR_PLL].mult,
152                              ibl.pllConfig[ibl_DDR_PLL].postdiv,
153                              ibl.pllConfig[ibl_MAIN_PLL].pllOutFreqMhz,
154                              ibl.pllConfig[ibl_DDR_PLL].pllOutFreqMhz);
155         if (ibl.ddrConfig.configDdr != 0)
156             hwEmif4p0Enable (&ibl.ddrConfig.uEmif.emif4p0);
157     }
160         
163 /**
164  *  @brief  Enable EMIF25 or SPI interface to the NAND
165  *
166  */
167 int32 deviceConfigureForNand(void)
170     return (0);
174 /**
175  *  @brief
176  *      Return the base memory address for emif25 in a given chip select space
177  */
178 uint32 deviceEmif25MemBase (int32 cs)
180     switch (cs)  {
182         case 2:  return (TARGET_MEM_NAND_CS_2);
184         case 3:  return (TARGET_MEM_NAND_CS_3);
186         case 4:  return (TARGET_MEM_NAND_CS_4);
188         case 5:  return (TARGET_MEM_NAND_CS_5);
190     }
192     return (0xffffffff);
197 /**
198  *  @brief
199  *      Return the PSC number for NAND/NOR through emif. Only 6678 has the emif
200  */
201 Int32 deviceEmifPscNum (void)
203     Uint32 v;
205     v = *((Uint32 *)DEVICE_JTAG_ID_REG);
206     v &= DEVICE_JTAG_ID_MASK;
207     if (v == DEVICE_C6678_JTAG_ID_VAL)
208         return (TARGET_PWR_EMIF_C6678);
210     /* Return a negative number to indicate no PSC module is associated with NAND */
211     return (-1);
217 /**
218  *  @brief
219  *    The e-fuse mac address is loaded
220  */
221 void deviceLoadDefaultEthAddress (uint8 *maddr)
223     uint32 macA, macB;
225     /* Read the e-fuse mac address */
226     macA = *((uint32 *)0x2620110);
227     macB = *((uint32 *)0x2620114);
229     maddr[0] = (macB >>  8) & 0xff;
230     maddr[1] = (macB >>  0) & 0xff;
231     maddr[2] = (macA >> 24) & 0xff;
232     maddr[3] = (macA >> 16) & 0xff;
233     maddr[4] = (macA >>  8) & 0xff;
234     maddr[5] = (macA >>  0) & 0xff;
238 /**
239  *  @brief
240  *    Compile time queue manager information
241  */
242 #define DEVICE_NUM_RX_CPPIS     1
243 #define DEVICE_NUM_TX_CPPIS     1
244 #define DEVICE_NUM_CPPIS        (DEVICE_NUM_RX_CPPIS + DEVICE_NUM_TX_CPPIS)
246 /* The linking RAM */
247 #pragma DATA_SECTION(qm_linkram_buf, ".linkram")
248 #pragma DATA_ALIGN(qm_linkram_buf, 16)
249 uint8 qm_linkram_buf[DEVICE_NUM_CPPIS * 2 * (sizeof(uint32)/sizeof(uint8))];
252 /* The CPPI RAM */
253 #pragma DATA_SECTION(qm_cppi_buf, ".cppi")
254 #pragma DATA_ALIGN(qm_cppi_buf, 16)
255 uint8 qm_cppi_buf[QM_DESC_SIZE_BYTES * DEVICE_NUM_CPPIS];
258 /* The rx data buffers */
259 #pragma DATA_SECTION(qm_buffer, ".mac_buffer")
260 #pragma DATA_ALIGN(qm_buffer, 16)
261 uint8 qm_buffer[MAX_SIZE_STREAM_BUFFER * DEVICE_NUM_RX_CPPIS];
263 const qmConfig_t qmConfig =  {
264     (UINT32) qm_linkram_buf,
265     sizeof  (qm_cppi_buf),
266     (UINT32) qm_cppi_buf,
268     DEVICE_NUM_CPPIS,
269     DEVICE_QM_FREE_Q
270 };
272 /**
273  *  @brief
274  *      Return the queue manager memory configuration information
275  */
276 void *targetGetQmConfig (void)
278     return ((void *)&qmConfig);
281 /**
282  *  @brief
283  *      Attach a packet buffer to each descriptor and push onto the linked buffer queue
284  */
285 void targetInitQs (void)
287     int32 i;
288     qmHostDesc_t *hd;
290     for (i = 0; i < DEVICE_NUM_RX_CPPIS; i++)  {
292         hd                = hwQmQueuePop (DEVICE_QM_FREE_Q);
293         hd->buffLen       = sizeof (qm_buffer) / DEVICE_NUM_CPPIS;
294         hd->buffPtr       = (UINT32) &(qm_buffer[MAX_SIZE_STREAM_BUFFER * i]);
295         hd->nextBDPtr     = 0;
296         hd->origBufferLen = MAX_SIZE_STREAM_BUFFER;
297         hd->origBuffPtr   = hd->buffPtr;
299         hwQmQueuePush (hd, DEVICE_QM_LNK_BUF_Q, QM_DESC_SIZE_BYTES);
301     }
304     for (i = 0; i < DEVICE_NUM_TX_CPPIS; i++)  {
306         hd                = hwQmQueuePop (DEVICE_QM_FREE_Q);
307         hd->buffLen       = 0;
308         hd->buffPtr       = 0;
309         hd->nextBDPtr     = 0;
310         hd->origBufferLen = 0;
311         hd->origBuffPtr   = 0;
313         hwQmQueuePush (hd, DEVICE_QM_TX_Q, QM_DESC_SIZE_BYTES);
315     }
322 const cpdmaRxCfg_t cpdmaEthRxCfg =  {
324     DEVICE_PA_CDMA_RX_CHAN_CFG_BASE,    /* Base address of PA CPDMA rx config registers */
325     DEVICE_PA_CDMA_RX_NUM_CHANNELS,     /* Number of rx channels */
327     DEVICE_PA_CDMA_RX_FLOW_CFG_BASE,    /* Base address of PA CPDMA rx flow registers */
328     DEVICE_PA_CDMA_RX_NUM_FLOWS,        /* Number of rx flows */
330     0,                                  /* Queue manager for descriptor / buffer for received packets */
331     DEVICE_QM_LNK_BUF_Q,                /* Queue of descriptors /buffers for received packets */
333     0,                                  /* Queue manager for received packets */
334     DEVICE_QM_RCV_Q,                    /* Queue for received packets (overridden by PA)  */
336     DEVICE_RX_CDMA_TIMEOUT_COUNT        /* Teardown maximum loop wait */
337 };
340 /**
341  *  @brief
342  *      Return the cpdma configuration information
343  */
344 void *targetGetCpdmaRxConfig (void)
346     return ((void *)&cpdmaEthRxCfg);
351 const cpdmaTxCfg_t cpdmaEthTxCfg = {
353     DEVICE_PA_CDMA_GLOBAL_CFG_BASE,     /* Base address of global config registers      */
354     DEVICE_PA_CDMA_TX_CHAN_CFG_BASE,    /* Base address of PA CPDMA tx config registers */
355     DEVICE_PA_CDMA_TX_NUM_CHANNELS      /* Number of tx channels */
357 };
360 /**
361  *  @brief
362  *      return the tx cpdma configuration information
363  */
364 void *targetGetCpdmaTxConfig (void)
366     return ((void *)&cpdmaEthTxCfg);
370 /**
371  *  @brief
372  *     Configure the PA
373  */
374 void targetPaConfig (uint8 *macAddr)
376     paConfig_t     paCfg;
377     qmHostDesc_t  *hd;
378     SINT16         ret;
380     /* Filter everything except the desired mac address and the broadcast mac */
381     paCfg.mac0ms = ((uint32)macAddr[0] << 24) | ((uint32)macAddr[1] << 16) | ((uint32)macAddr[2] << 8) | (uint32)(macAddr[3]);
382     paCfg.mac0ls = ((uint32)macAddr[4] << 24) | ((uint32)macAddr[5] << 16);
384     paCfg.mac1ms = 0xffffffff;
385     paCfg.mac1ls = 0xffff0000;
387     paCfg.rxQnum = DEVICE_QM_RCV_Q;
389     /* Form the configuration command in a buffer linked to a descriptor */
390     hd = hwQmQueuePop (DEVICE_QM_LNK_BUF_Q);
391     paCfg.cmdBuf = (uint8 *)hd->origBuffPtr;
393     ret = hwPaEnable (&paCfg);
394     if (ret != 0)  {
395         iblStatus.iblFail = ibl_FAIL_CODE_PA;
396         return;
397     }
400     /* Send the command to the PA through the QM */
401     hd->softwareInfo0 = PA_MAGIC_ID;
402     hd->buffLen = 16;
403     QM_DESC_DESCINFO_SET_PKT_LEN(hd->descInfo, 16);
405     /* Set the return Queue */
406     QM_DESC_PINFO_SET_QM    (hd->packetInfo, 0);
407     QM_DESC_PINFO_SET_QUEUE (hd->packetInfo, DEVICE_QM_LNK_BUF_Q);
409     hwQmQueuePush (hd, DEVICE_QM_PA_CFG_Q, QM_DESC_SIZE_BYTES);
414 /**
415  *  @brief
416  *      Chip level SGMII serdes configuration
417  *
418  *  @details
419  *      Both lanes are always setup, regardless of the port value
420  */
421 void targetSgmiiSerdesConfig (int32 port, void *viblSgmii)
423   serdesConfig_t scfg;
424   iblSgmii_t     *sgmii = (iblSgmii_t *)viblSgmii;
426   scfg.cfg      = sgmii->auxConfig;
427   scfg.nLanes   = 2;
428   scfg.rxCfg[0] = scfg.rxCfg[1] = sgmii->rxConfig;
429   scfg.txCfg[0] = scfg.txCfg[1] = sgmii->txConfig;
431   hwSerdesConfig (TARGET_SGMII_SERDES_BASE, &scfg);
433   hwSerdesWaitLock (TARGET_SGMII_SERDES_STATUS_BASE);
438 Int32 targetMacSend (void *vptr_device, Uint8* buffer, int num_bytes) 
440     qmHostDesc_t   *hd;
441     NET_DRV_DEVICE *ptr_device = (NET_DRV_DEVICE *)vptr_device;
442     int             i;
445     /* Must always setup the descriptor to have the minimum packet length */
446     if (num_bytes < 64)
447         num_bytes = 64;
450     for (i = 0, hd = NULL; hd == NULL; i++, chipDelay32 (1000)) 
451         hd = hwQmQueuePop (DEVICE_QM_TX_Q);
452     
453     if (hd == NULL)
454         return (-1);
456     QM_DESC_DESCINFO_SET_PKT_LEN(hd->descInfo, num_bytes);
458     hd->buffLen       = num_bytes;
459     hd->origBufferLen = num_bytes;
461     hd->buffPtr     = deviceLocalAddrToGlobal((UINT32)buffer);
462     hd->origBuffPtr = deviceLocalAddrToGlobal((UINT32)buffer);
464     
465     /* Return the descriptor back to the transmit queue */
466     QM_DESC_PINFO_SET_QM(hd->packetInfo, 0);
467     QM_DESC_PINFO_SET_QUEUE(hd->packetInfo, DEVICE_QM_TX_Q);
469     hwQmQueuePush (hd, DEVICE_QM_ETH_TX_Q, QM_DESC_SIZE_BYTES);
471     return (0);
476 Int32 targetMacRcv (void *vptr_device, UINT8 *buffer)
478     Int32           pktSizeBytes; 
479     qmHostDesc_t   *hd;
480     NET_DRV_DEVICE *ptr_device = (NET_DRV_DEVICE *)vptr_device;
482     hd = hwQmQueuePop (DEVICE_QM_RCV_Q);
483     if (hd == NULL)
484         return (0);
486     pktSizeBytes = QM_DESC_DESCINFO_GET_PKT_LEN(hd->descInfo);
487     iblMemcpy ((void *)buffer, (void *)hd->buffPtr, pktSizeBytes);
489     hd->buffLen = hd->origBufferLen;
490     hd->buffPtr = hd->origBuffPtr;
492     hwQmQueuePush (hd, DEVICE_QM_LNK_BUF_Q, QM_DESC_SIZE_BYTES);
494     return (pktSizeBytes);
498 void targetFreeQs (void)
500     qmHostDesc_t   *hd;
502     do  {
504         hd = hwQmQueuePop (DEVICE_QM_FREE_Q);
506     } while (hd != NULL);
508     do  {
510         hd = hwQmQueuePop (DEVICE_QM_LNK_BUF_Q);
512     } while (hd != NULL);
513     
514     do  {
516         hd = hwQmQueuePop (DEVICE_QM_RCV_Q);
518     } while (hd != NULL);
519     
520     do  {
522         hd = hwQmQueuePop (DEVICE_QM_TX_Q);
524     } while (hd != NULL);
525     
526 }    
528 extern nandCtbl_t nandEmifCtbl;
529 /**
530  *  @brief Return the NAND interface (GPIO, EMIF25 or SPI) used based on the value
531  *         of interface
532  */
533 #ifndef EXCLUDE_NAND_GPIO
534 nandCtbl_t nandGpioCtbl =  {
536     nandHwGpioDriverInit,
537     nandHwGpioDriverReadBytes,
538     nandHwGpioDriverReadPage,
539     nandHwGpioDriverClose
541 };
542 #endif
544 #ifndef EXCLUDE_NAND_EMIF
545 extern Int32 nandHwEmifDriverInit (int32 cs, void *vdevInfo);
546 extern Int32 nandHwEmifDriverReadBytes (Uint32 block, Uint32 page, Uint32 byte, Uint32 nbytes, Uint8 *data);
547 extern Int32 nandHwEmifDriverReadPage (Uint32 block, Uint32 page, Uint8 *data);
548 extern Int32 nandHwEmifDriverClose (void);
550 nandCtbl_t nandEmifCtbl =  {
552     nandHwEmifDriverInit,
553     nandHwEmifDriverReadBytes,
554     nandHwEmifDriverReadPage,
555     nandHwEmifDriverClose
557 };
558 #endif
560 #ifndef EXCLUDE_NAND_SPI
561 nandCtbl_t nandSpiCtbl =  {
564     nandHwSpiDriverInit,
565     nandHwSpiDriverReadBytes,
566     nandHwSpiDriverReadPage,
567     nandHwSpiDriverClose
569 };
570 #endif
572 nandCtbl_t *deviceGetNandCtbl (int32 interface)
574 #ifndef EXCLUDE_NAND_GPIO
576     if (interface == ibl_PMEM_IF_GPIO)
577         return (&nandGpioCtbl);
579 #endif
581 #ifndef EXCLUDE_NAND_SPI
583     if (interface == ibl_PMEM_IF_SPI)
584         return (&nandSpiCtbl);
586 #endif
588 #ifndef EXCLUDE_NAND_EMIF
590     if ((interface >= ibl_PMEM_IF_CHIPSEL_2) && (interface <= ibl_PMEM_IF_CHIPSEL_5))
591         return (&nandEmifCtbl);
593 #endif
595     return (NULL);
600 /**
601  * @brief
602  *      Get the nor call table for the specified nor interface
603  */
605 #ifndef EXCLUDE_NOR_EMIF
606 norCtbl_t norEmifCtbl = {
607     
608     norHwEmifDriverInit,
609     norHwEmifDriverReadBytes,
610     norHwEmifDriverClose
612 };
614 #endif
616 #ifndef EXCLUDE_NOR_SPI
618 norCtbl_t norSpiCtbl = {
619     
620     norHwSpiDriverInit,
621     norHwSpiDriverReadBytes,
622     norHwSpiDriverClose
624 };
626 #endif
628 norCtbl_t *deviceGetNorCtbl (int32 interface)
631 #ifndef EXCLUDE_NOR_SPI
632     
633     if (interface == ibl_PMEM_IF_SPI)
634         return (&norSpiCtbl);
636 #endif
638 #ifndef EXCLUDE_NOR_EMIF
639    
640     if ((interface >= ibl_PMEM_IF_CHIPSEL_2) && (interface <= ibl_PMEM_IF_CHIPSEL_5))
641         return (&norEmifCtbl);
643 #endif
645     return (NULL);
648     
651     
657