Added SRIO boot example, added binary support for writers
[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
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     }
118 uint32_t swap (uint32_t v)
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);
131 /******************************************************************************
132  * Function:    print_platform_errno
133  ******************************************************************************/
134 void
135 print_platform_errno
137     void
140     printf ("Returned platform error number is %d\n", platform_errno);
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)
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);
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)
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);
271 /******************************************************************************
272  * Function:    Send a maintenance packet
273  ******************************************************************************/
274 void
275 mainPacket
277     uint32_t    addr,
278     uint32_t    value
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;
340 /* Return if Port is OK or not */
341 int32_t SRIOPortStatus(uint32_t port_num)
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);
375 void
376 srio_init
378     uint32_t    port_num,
379     uint32_t    loopback
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);
403 void main (void)
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 (;;);