[keystone-rtos/mcsdk-tools.git] / boot_loader / examples / srio / srioboot_example / src / srioBootExample.c
1 /******************************************************************************
2 * Copyright (c) 2011 Texas Instruments Incorporated - http://www.ti.com
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *
11 * Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the
14 * distribution.
15 *
16 * Neither the name of Texas Instruments Incorporated nor the names of
17 * its contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 *****************************************************************************/
33 #include <stdlib.h>
34 #include <stdio.h>
35 #include <string.h>
36 #include "platform.h"
37 #include "srioDdrInit.h"
38 #include "srioBootCode.h"
40 #define DEVICE_REG32_W(x,y) *(volatile uint32_t *)(x)=(y)
41 #define DEVICE_REG32_R(x) (*(volatile uint32_t *)(x))
43 #ifdef _EVMC6678L_
44 #define MAGIC_ADDR 0x87fffc
45 #endif
47 #ifdef _EVMC6670L_
48 #define MAGIC_ADDR 0x87fffc
49 #endif
51 #define BOOT_MAGIC_ADDR(x) (MAGIC_ADDR + (1<<28) + (x<<24))
53 /* Entry address of the boot image */
54 #define BOOT_ENTRY_ADDR 0xc000000
56 /* Maximum number of bytes per transfer */
57 #define MAX_TX_SIZE 1024
59 /* SRIO transfer wait timeout in usec */
60 #define WAIT_TIMEOUT 500000
62 /* SRIO Boot Example Version */
63 char version[] = "01.00.00.01";
65 uint32_t coreNum;
67 /* These can be changed on the fly during the test */
68 volatile uint32_t port = 0;
69 volatile uint32_t rio_id = 0;
70 volatile uint32_t loopback = 0;
72 #pragma DATA_ALIGN(bootEntryAddr, 16)
73 volatile uint32_t bootEntryAddr = BOOT_ENTRY_ADDR; /* Base address of MSMC */
76 /* Port error status registers */
77 #define SRIO_PORT_ERR_STATUS_REG(x) (0x290b158 + x*0x20)
79 /* Convert bytes to 32 bits */
80 uint32_t byteto32bits(uint8_t *pDspCode)
81 {
82 int32_t i;
83 uint32_t temp;
85 temp = *pDspCode++;
86 for(i=0; i<3;i++) {
87 temp <<= 8;
88 temp |= *pDspCode++;
89 }
90 return(temp);
91 }
94 /* Convert to big endian, if the .out to be booted is big endian, this is not required */
95 void
96 Convert2BigEndian
97 (
98 uint32_t *pDspCode,
99 int32_t size
100 )
101 {
102 uint32_t i;
103 uint32_t temp;
105 for(i=0; i<size; i+=4, pDspCode++) {
106 temp = *pDspCode;
108 temp = (temp>>24) |
109 ((temp<<8) & 0x00FF0000) |
110 ((temp>>8) & 0x0000FF00) |
111 (temp<<24);
113 *pDspCode= temp;
114 }
115 }
118 uint32_t swap (uint32_t v)
119 {
120 uint32_t w;
122 w = (((v >> 24) & 0xff) << 0) |
123 (((v >> 16) & 0xff) << 8) |
124 (((v >> 8) & 0xff) << 16) |
125 (((v >> 0) & 0xff) << 24) ;
127 return (w);
129 }
131 /******************************************************************************
132 * Function: print_platform_errno
133 ******************************************************************************/
134 void
135 print_platform_errno
136 (
137 void
138 )
139 {
140 printf ("Returned platform error number is %d\n", platform_errno);
141 }
144 /*
145 Transfer (size_bytes) bytes data from host address (host_addr) to device ID's
146 (rio_id) global address (dsp_addr). Lane 0 is used for booting.
148 rio_id: destination device id
149 host_addr: host's address
150 dsp_addr: target dsp's global address
151 size_bytes: size in bytes
152 */
153 int SRIOTransfer(int rio_num, int port_num, unsigned int host_addr, unsigned int dsp_addr, int size_bytes)
154 {
155 unsigned int count,busy;
157 /* Program a transfer on port 0 */
158 /* LSU 1 Reg 0 - MSB of destination */
159 DEVICE_REG32_W(0x2900d00, 0x00000000);
162 /* LSU 1 Reg 1 - LSB of destination */
163 DEVICE_REG32_W(0x2900d04, dsp_addr);
166 /* LSU 1 Reg 2 - source address */
167 DEVICE_REG32_W(0x2900d08, (1 << 28) | (coreNum << 24) | host_addr);
170 /* LSU 1 Reg 3 - Byte count */
171 DEVICE_REG32_W(0x2900d0c, size_bytes);
174 /* LSU 1 Reg 4 -
175 * out port ID = 0
176 * Priority = 2
177 * XAM = 0
178 * ID size = 1 (16 bit)
179 * Dest ID specified as arg
180 * int32_terrupt request = 0 */
181 DEVICE_REG32_W(0x2900d10, 0x00000000 | (rio_num << 8)| (port_num << 30));
184 /* LSU 1 Reg 5 -
185 * doorbell info = 0 for this packet type
186 * hop count = 0 for this packet type
187 * Packet type = 0x54 - ftype = 5, ttype = 4
188 * nwrite packet type.
189 * Writing this register should initiate the transfer */
190 DEVICE_REG32_W(0x2900d14, 0x00000054);
192 /* wait for it to complete */
193 count = 0;
195 /* wait for it to complete */
196 do{
197 platform_delay(1);
198 count++;
199 if (count >= WAIT_TIMEOUT)
200 {
201 return (-1);
202 } busy = DEVICE_REG32_R(0x2900d18);
204 } while ((busy & 0x80000000) != 0x00000000);
206 return(0);
207 }
210 /* Send boot tables to DSP and then write the magic address to boot the DSP
212 pDspCode: points to DSP code;
213 DeviceID: device ID.
215 */
216 int32_t pushData2Srio(uint8_t *pDspCode,int32_t DeviceID)
217 {
218 uint32_t i;
219 uint32_t size;
220 uint32_t count, remainder;
221 uint32_t startaddr;
222 volatile uint32_t vx;
225 /* Claim the LSU */
226 vx = DEVICE_REG32_R(0x2900d18);
228 /* Get the boot entry address */
229 bootEntryAddr = byteto32bits(pDspCode);
230 pDspCode +=4;
232 while(1) {
234 /* Get the size */
235 size = byteto32bits(pDspCode);
236 if(size == 0) break;
237 pDspCode += 4;
239 startaddr = byteto32bits(pDspCode);
240 pDspCode+= 4;
242 count = size/MAX_TX_SIZE;
243 remainder = size - count * MAX_TX_SIZE;
245 for(i=0; i<count; i++) {
246 /* This is not needed if the .out to be booted is big endian already */
247 Convert2BigEndian((uint32_t *)pDspCode,MAX_TX_SIZE);
249 /* Transfer boot tables to DSP */
250 if(SRIOTransfer(rio_id, port, (uint32_t )pDspCode, (uint32_t )startaddr, MAX_TX_SIZE)!=0) return(-1);
251 pDspCode += MAX_TX_SIZE;
252 startaddr += MAX_TX_SIZE;
253 }
255 /* This is not needed if the .out to be booted is big endian already */
256 Convert2BigEndian((uint32_t *)pDspCode,remainder);
258 if(SRIOTransfer(rio_id, port,(uint32_t )pDspCode, (uint32_t )startaddr, remainder)!=0) return(-1);
259 pDspCode += remainder;
260 }
262 /* Write to Core 0 boot magic address to boot Core 0 */
263 if (SRIOTransfer(rio_id, port,(uint32_t )&bootEntryAddr, BOOT_MAGIC_ADDR(0), 4)!=0)
264 return(-1);
266 return(0);
267 }
271 /******************************************************************************
272 * Function: Send a maintenance packet
273 ******************************************************************************/
274 void
275 mainPacket
276 (
277 uint32_t addr,
278 uint32_t value
279 )
280 {
281 volatile uint32_t vx;
282 uint32_t busy, count;
284 value = swap(value);
286 /* Claim the LSU */
287 vx = DEVICE_REG32_R(0x2900d18);
289 /* Program a transfer on port 0 */
290 /* LSU 1 Reg 0 - MSB of destination */
291 DEVICE_REG32_W(0x2900d00, 0x00000000);
294 /* LSU 1 Reg 1 - LSB of destination */
295 DEVICE_REG32_W(0x2900d04, addr - 0x290b000);
297 /* LSU 1 Reg 2 - source address */
298 DEVICE_REG32_W(0x2900d08, (1 << 28) | (coreNum << 24) | (uint32_t)&value);
301 /* LSU 1 Reg 3 - Byte count */
302 DEVICE_REG32_W(0x2900d0c, 4);
304 /* LSU 1 Reg 4 -
305 * out port ID = 0
306 * Priority = 2
307 * XAM = 0
308 * ID size = 1 (16 bit)
309 * Dest ID specified as arg
310 * int32_terrupt request = 0 */
311 DEVICE_REG32_W(0x2900d10, 0xffff0000 | (port << 8));
314 /* LSU 1 Reg 5 -
315 * doorbell info = 0 for this packet type
316 * hop count = 0 for this packet type
317 * Packet type = 0x54 - ftype = 5, ttype = 4
318 * nwrite packet type.
319 * Writing this register should initiate the transfer */
320 /* *((uint32_t *)0x2900d14) = 0x00000054; */
321 DEVICE_REG32_W(0x2900d14, 0x00000081); /* maint32_tenance write */
323 /* wait for it to complete */
324 count = 0;
325 do{
326 platform_delay(1);
327 count++;
328 if (count >= WAIT_TIMEOUT)
329 {
330 printf("Send a maintenance packet failed\n");
331 return;
332 }
333 busy = DEVICE_REG32_R(0x2900d18);
335 } while ((busy & 0x80000000) != 0x00000000);
337 return;
338 }
340 /* Return if Port is OK or not */
341 int32_t SRIOPortStatus(uint32_t port_num)
342 {
343 uint32_t count,value,portok;
345 count = 0;
346 portok= 0;
348 while(1)
349 {
350 value = DEVICE_REG32_R(SRIO_PORT_ERR_STATUS_REG(port_num));
352 if((value & 0x02) !=0)
353 {
354 portok++;
355 if(portok >= 50)
356 {
357 break; /* port must be solid OK */
358 }
359 }
360 else
361 {
362 portok = 0;
363 count++;
364 if (count >= WAIT_TIMEOUT)
365 {
366 return(-1);
367 }
368 }
369 platform_delay(1);
370 }
372 return(0);
373 }
375 void
376 srio_init
377 (
378 uint32_t port_num,
379 uint32_t loopback
380 )
381 {
382 /* Enable the Transmit register */
383 DEVICE_REG32_W(0x290b13c, 0x40000000);
385 if (loopback)
386 {
387 /* Enable Lane loop back for all the ports */
388 DEVICE_REG32_W(0x2900018, 0x000000f0);
389 }
391 /* check for the port status */
392 if (SRIOPortStatus(port_num) != 0)
393 {
394 printf("Port %d is not OK!\n", port_num);
395 }
397 /* TLM SP0 control, enable promiscuous mode */
398 mainPacket (0x291b380, 0x00309000);
400 mainPacket (0x290b15c, 0x00600000);
401 }
403 void main (void)
404 {
405 platform_init_flags init_flags;
406 platform_init_config init_config;
407 char version_msg[] = "\r\n\r\nSRIO Boot Host Example Version ";
409 printf("%s%s\n\n", version_msg, version);
411 /* Initialize main Platform lib */
412 memset(&init_config, 0, sizeof(platform_init_config));
413 memset(&init_flags, 1, sizeof(platform_init_flags));
414 if (platform_init(&init_flags, &init_config) != Platform_EOK)
415 {
416 printf ("Platform init failed!\n");
417 print_platform_errno();
418 return;
419 }
421 coreNum = platform_get_coreid();
423 /* Init port 0, disable loopback */
424 srio_init(port, loopback);
426 /* Push the DDR init code to remote DSP core 0 and boot core 0 to initialize the DDR */
427 if(pushData2Srio(ddrInitCode, rio_id)==0)
428 {
429 printf("Transfer DDR init code via SRIO successfully\n");
431 platform_delay(1000);
433 /* Push the boot image code to remote DSP DDR and boot core 0 to run Hello World */
434 if(pushData2Srio(bootCode, rio_id)==0)
435 {
436 printf("Transfer boot code via SRIO successfully\n");
437 }
438 else
439 {
440 printf("DSP boot failed.\n");
441 }
442 }
443 else
444 {
445 printf("DSP boot failed.\n");
446 }
448 for (;;);
450 }