1 /*
2 *
3 * Copyright (C) 2011-12 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>
68 #include <stdint.h>
69 #include "target.h"
70 #include "uart.h"
72 #define PLL_DDR_INIT_LOOPMAX 10
73 #define IBL_RESULT_CODE_STR_LEN 20
74 #define IBL_RESULT_CODE_LOC 17
76 extern cregister unsigned int DNUM;
78 /**
79 * @brief Determine if an address is local
80 *
81 * @details
82 * Examines an input address to determine if it is a local address. Using the largest
83 * L2 size on the C6657.
84 */
85 bool address_is_local (Uint32 addr)
86 {
87 /* L2 */
88 if ((addr >= 0x00800000) && (addr < 0x00900000))
89 return (TRUE);
91 /* L1P */
92 if ((addr >= 0x00e00000) && (addr < 0x00e08000))
93 return (TRUE);
95 /* L2D */
96 if ((addr >= 0x00f00000) && (addr < 0x00f08000))
97 return (TRUE);
99 return (FALSE);
101 }
104 /**
105 * @brief Convert a local l1d, l1p or l2 address to a global address
106 *
107 * @details
108 * The global address is formed. If the address is not local then
109 * the input address is returned
110 */
111 Uint32 deviceLocalAddrToGlobal (Uint32 addr)
112 {
114 if (address_is_local (addr))
115 addr = (1 << 28) | (DNUM << 24) | addr;
117 return (addr);
119 }
122 /**
123 * @brief
124 * Enable the DDR
125 *
126 * @details
127 * The DDR controller on the c66x is an emif 4.0. The controller is
128 * initialized directly with the supplied values
129 */
130 void deviceDdrConfig (void)
131 {
132 uint32 loopcount=0;
133 int8 ddr_result_code_str[IBL_RESULT_CODE_STR_LEN] = "IBL Result code 0";
134 /* The emif registers must be made visible. MPAX mapping 2 is used */
135 DEVICE_REG_XMPAX_L(2) = 0x10000000 | 0xff; /* replacement addr + perm*/
136 DEVICE_REG_XMPAX_H(2) = 0x2100000B; /* base addr + seg size (64KB)*/
138 if (ibl.ddrConfig.configDdr != 0)
139 hwEmif4p0Enable (&ibl.ddrConfig.uEmif.emif4p0);
141 }
145 /**
146 * @brief Enable EMIF25 or SPI interface to the NAND
147 *
148 */
149 int32 deviceConfigureForNand(void)
150 {
152 return (0);
154 }
156 /**
157 * @brief
158 * Return the base memory address for emif25 in a given chip select space
159 */
160 uint32 deviceEmif25MemBase (int32 cs)
161 {
162 switch (cs) {
164 case 2: return (TARGET_MEM_NAND_CS_2);
166 case 3: return (TARGET_MEM_NAND_CS_3);
168 case 4: return (TARGET_MEM_NAND_CS_4);
170 case 5: return (TARGET_MEM_NAND_CS_5);
172 }
174 return (0xffffffff);
176 }
179 /**
180 * @brief
181 * Return the PSC number for NAND/NOR through emif.
182 */
183 Int32 deviceEmifPscNum (void)
184 {
185 Uint32 v;
187 v = *((Uint32 *)DEVICE_JTAG_ID_REG);
188 v &= DEVICE_JTAG_ID_MASK;
189 if (v == DEVICE_C6657_JTAG_ID_VAL)
190 return (TARGET_PWR_EMIF_C6657);
192 /* Return a negative number to indicate no PSC module is associated with NAND */
193 return (-1);
195 }
199 /**
200 * @brief
201 * The e-fuse mac address is loaded
202 */
203 void deviceLoadDefaultEthAddress (uint8 *maddr)
204 {
205 uint32 macA, macB;
207 /* Read the e-fuse mac address */
208 macA = *((uint32 *)0x2620110);
209 macB = *((uint32 *)0x2620114);
211 maddr[0] = (macB >> 8) & 0xff;
212 maddr[1] = (macB >> 0) & 0xff;
213 maddr[2] = (macA >> 24) & 0xff;
214 maddr[3] = (macA >> 16) & 0xff;
215 maddr[4] = (macA >> 8) & 0xff;
216 maddr[5] = (macA >> 0) & 0xff;
217 }
219 extern nandCtbl_t nandEmifCtbl;
220 /**
221 * @brief Return the NAND interface (GPIO, EMIF25 or SPI) used based on the value
222 * of interface
223 */
224 #ifndef EXCLUDE_NAND_GPIO
225 nandCtbl_t nandGpioCtbl = {
227 nandHwGpioDriverInit,
228 nandHwGpioDriverReadBytes,
229 nandHwGpioDriverReadPage,
230 nandHwGpioDriverClose
232 };
233 #endif
235 #ifndef EXCLUDE_NAND_EMIF
236 extern Int32 nandHwEmifDriverInit (int32 cs, void *vdevInfo);
237 extern Int32 nandHwEmifDriverReadBytes (Uint32 block, Uint32 page, Uint32 byte, Uint32 nbytes, Uint8 *data);
238 extern Int32 nandHwEmifDriverReadPage (Uint32 block, Uint32 page, Uint8 *data);
239 extern Int32 nandHwEmifDriverClose (void);
241 nandCtbl_t nandEmifCtbl = {
243 nandHwEmifDriverInit,
244 nandHwEmifDriverReadBytes,
245 nandHwEmifDriverReadPage,
246 nandHwEmifDriverClose
248 };
249 #endif
251 #ifndef EXCLUDE_NAND_SPI
252 nandCtbl_t nandSpiCtbl = {
255 nandHwSpiDriverInit,
256 nandHwSpiDriverReadBytes,
257 nandHwSpiDriverReadPage,
258 nandHwSpiDriverClose
260 };
261 #endif
263 nandCtbl_t *deviceGetNandCtbl (int32 interface)
264 {
265 #ifndef EXCLUDE_NAND_GPIO
267 if (interface == ibl_PMEM_IF_GPIO)
268 return (&nandGpioCtbl);
270 #endif
272 #ifndef EXCLUDE_NAND_SPI
274 if (interface == ibl_PMEM_IF_SPI)
275 return (&nandSpiCtbl);
277 #endif
279 #ifndef EXCLUDE_NAND_EMIF
281 if ((interface >= ibl_PMEM_IF_CHIPSEL_2) && (interface <= ibl_PMEM_IF_CHIPSEL_5))
282 return (&nandEmifCtbl);
284 #endif
286 return (NULL);
288 }
291 /**
292 * @brief
293 * Get the nor call table for the specified nor interface
294 */
296 #ifndef EXCLUDE_NOR_EMIF
297 norCtbl_t norEmifCtbl = {
299 norHwEmifDriverInit,
300 norHwEmifDriverReadBytes,
301 norHwEmifDriverClose
303 };
305 #endif
307 #ifndef EXCLUDE_NOR_SPI
309 norCtbl_t norSpiCtbl = {
311 norHwSpiDriverInit,
312 norHwSpiDriverReadBytes,
313 norHwSpiDriverClose
315 };
317 #endif
319 norCtbl_t *deviceGetNorCtbl (int32 interface)
320 {
322 #ifndef EXCLUDE_NOR_SPI
324 if (interface == ibl_PMEM_IF_SPI)
325 return (&norSpiCtbl);
327 #endif
329 #ifndef EXCLUDE_NOR_EMIF
331 if ((interface >= ibl_PMEM_IF_CHIPSEL_2) && (interface <= ibl_PMEM_IF_CHIPSEL_5))
332 return (&norEmifCtbl);
334 #endif
336 return (NULL);
338 }
340 /**
341 * @brief
342 * Chip level SGMII serdes configuration
343 *
344 * @details
345 * Both lanes are always setup, regardless of the port value
346 */
347 void targetSgmiiSerdesConfig (int32 port, void *viblSgmii)
348 {
349 serdesConfig_t scfg;
350 iblSgmii_t *sgmii = (iblSgmii_t *)viblSgmii;
352 scfg.cfg = sgmii->auxConfig;
353 scfg.nLanes = 2;
354 scfg.rxCfg[0] = scfg.rxCfg[1] = sgmii->rxConfig;
355 scfg.txCfg[0] = scfg.txCfg[1] = sgmii->txConfig;
357 hwSerdesConfig (TARGET_SGMII_SERDES_BASE, &scfg);
359 hwSerdesWaitLock (TARGET_SGMII_SERDES_STATUS_BASE);
361 }