Fixed C6670 SRIO boot issue
[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"
39 #include "ti/csl/csl_semAux.h"
41 #define DEVICE_REG32_W(x,y)   *(volatile uint32_t *)(x)=(y)
42 #define DEVICE_REG32_R(x)    (*(volatile uint32_t *)(x))
44 #ifdef _EVMC6678L_
45 #define MAGIC_ADDR     0x87fffc
46 #endif
48 #ifdef _EVMC6670L_
49 #define MAGIC_ADDR     0x8ffffc
50 #endif
52 #define BOOT_MAGIC_ADDR(x)  (MAGIC_ADDR + (1<<28) + (x<<24))
54 /* Entry address of the boot image */
55 #define BOOT_ENTRY_ADDR     0xc000000
57 /* Maximum number of bytes per transfer */
58 #define MAX_TX_SIZE         1024
60 /* SRIO transfer wait timeout in usec */
61 #define WAIT_TIMEOUT        500000
63 /* SRIO Boot Example Version */
64 char version[] = "01.00.00.01";
66 uint32_t coreNum;
68 /* These can be changed on the fly during the test */
69 volatile uint32_t port      = 0;
70 volatile uint32_t rio_id    = 0;
71 volatile uint32_t loopback  = 0;
73 #pragma DATA_ALIGN(bootEntryAddr, 16)
74 volatile uint32_t bootEntryAddr = BOOT_ENTRY_ADDR;  /* Base address of MSMC */
77 /* Port error status registers */
78 #define SRIO_PORT_ERR_STATUS_REG(x)    (0x290b158 + x*0x20)
80 /* OSAL functions for Platform Library */
81 uint8_t *Osal_platformMalloc (uint32_t num_bytes, uint32_t alignment)
82 {
83         return malloc(num_bytes);
84 }
86 void Osal_platformFree (uint8_t *dataPtr, uint32_t num_bytes)
87 {
88     /* Free up the memory */
89     if (dataPtr)
90     {
91         free(dataPtr);
92     }
93 }
95 /* Convert bytes to 32 bits */
96 uint32_t byteto32bits(uint8_t *pDspCode)
97 {
98     int32_t i;
99     uint32_t temp;
101     temp = *pDspCode++;
102     for(i=0; i<3;i++) {
103         temp <<= 8;
104         temp |= *pDspCode++;
105     }
106     return(temp);
109 void Osal_platformSpiCsEnter(void)
111     /* Get the hardware semaphore.
112      *
113      * Acquire Multi core CPPI synchronization lock
114      */
115     while ((CSL_semAcquireDirect (3)) == 0);
117     return;
120 void Osal_platformSpiCsExit (void)
122     /* Release the hardware semaphore
123      *
124      * Release multi-core lock.
125      */
126     CSL_semReleaseSemaphore (3);
128     return;
132 /* Convert to big endian, if the .out to be booted is big endian, this is not required */
133 void
134 Convert2BigEndian
136     uint32_t    *pDspCode,
137     int32_t     size
140     uint32_t i;
141     uint32_t temp;
143     for(i=0; i<size; i+=4, pDspCode++) {
144         temp = *pDspCode;
146         temp =  (temp>>24) |
147             ((temp<<8) & 0x00FF0000) |
148             ((temp>>8) & 0x0000FF00) |
149             (temp<<24);
151         *pDspCode= temp;
152     }
156 uint32_t swap (uint32_t v)
158     uint32_t w;
160     w = (((v >> 24) & 0xff) <<  0)  |
161         (((v >> 16) & 0xff) <<  8)  |
162         (((v >>  8) & 0xff) << 16)  |
163         (((v >>  0) & 0xff) << 24)  ;
165     return (w);
169 /******************************************************************************
170  * Function:    print_platform_errno
171  ******************************************************************************/
172 void
173 print_platform_errno
175     void
178     printf ("Returned platform error number is %d\n", platform_errno);
182 /*
183 Transfer (size_bytes) bytes data from host address (host_addr) to device ID's
184 (rio_id) global address (dsp_addr). Lane 0 is used for booting.
186   rio_id:    destination device id
187   host_addr:  host's address
188   dsp_addr:   target dsp's global address
189   size_bytes: size in bytes
190 */
191 int SRIOTransfer(int rio_num, int port_num, unsigned int host_addr, unsigned int dsp_addr, int size_bytes)
193     unsigned int count,busy;
195     /* Program a transfer on port 0 */
196     /* LSU 1 Reg 0 - MSB of destination */
197     DEVICE_REG32_W(0x2900d00, 0x00000000);
200     /* LSU 1 Reg 1 - LSB of destination */
201     DEVICE_REG32_W(0x2900d04, dsp_addr);
204     /* LSU 1 Reg 2 - source address */
205     DEVICE_REG32_W(0x2900d08, (1 << 28) | (coreNum << 24) | host_addr);
208     /* LSU 1 Reg 3 - Byte count */
209     DEVICE_REG32_W(0x2900d0c, size_bytes);
212     /* LSU 1 Reg 4 -
213     * out port ID = 0
214     * Priority = 2
215     * XAM = 0
216     * ID size = 1 (16 bit)
217     * Dest ID specified as arg
218     * int32_terrupt request = 0 */
219     DEVICE_REG32_W(0x2900d10, 0x00000000 | (rio_num << 8)| (port_num << 30));
222     /* LSU 1 Reg 5 -
223     * doorbell info = 0 for this packet type
224     * hop count = 0 for this packet type
225     * Packet type = 0x54 - ftype = 5, ttype = 4
226     *                      nwrite packet type.
227     * Writing this register should initiate the transfer */
228     DEVICE_REG32_W(0x2900d14, 0x00000054);
230     /* wait for it to complete */
231     count = 0;
233     /* wait for it to complete */
234     do{
235         platform_delay(1);
236         count++;
237         if (count >= WAIT_TIMEOUT)
238         {
239             return (-1);
240         }        busy = DEVICE_REG32_R(0x2900d18);
242     } while ((busy & 0x80000000) != 0x00000000);
244     return(0);
248 /* Send boot tables to DSP and then write the magic address to boot the DSP
250 pDspCode: points to DSP code;
251 DeviceID: device ID.
253 */
254 int32_t pushData2Srio(uint8_t *pDspCode,int32_t DeviceID)
256     uint32_t i;
257     uint32_t size;
258     uint32_t count, remainder;
259     uint32_t startaddr;
260     volatile uint32_t vx;
263     /* Claim the LSU */
264     vx = DEVICE_REG32_R(0x2900d18);
266     /* Get the boot entry address */
267     bootEntryAddr = byteto32bits(pDspCode);
268     pDspCode +=4;
270     while(1) {
272         /* Get the size */
273         size =  byteto32bits(pDspCode);
274         if(size == 0) break;
275         pDspCode += 4;
277         startaddr = byteto32bits(pDspCode);
278         pDspCode+= 4;
280         count = size/MAX_TX_SIZE;
281         remainder = size - count * MAX_TX_SIZE;
283         for(i=0; i<count; i++) {
284             /* This is not needed if the .out to be booted is big endian already */
285             Convert2BigEndian((uint32_t *)pDspCode,MAX_TX_SIZE);
287             /* Transfer boot tables to DSP */
288             if(SRIOTransfer(rio_id, port, (uint32_t )pDspCode, (uint32_t )startaddr, MAX_TX_SIZE)!=0) return(-1);
289             pDspCode += MAX_TX_SIZE;
290             startaddr += MAX_TX_SIZE;
291         }
293         /* This is not needed if the .out to be booted is big endian already */
294         Convert2BigEndian((uint32_t *)pDspCode,remainder);
296         if(SRIOTransfer(rio_id, port,(uint32_t )pDspCode, (uint32_t )startaddr, remainder)!=0) return(-1);
297         pDspCode += remainder;
298     }
300     /* Write to Core 0 boot magic address to boot Core 0 */
301     if (SRIOTransfer(rio_id, port,(uint32_t )&bootEntryAddr, BOOT_MAGIC_ADDR(0), 4)!=0)
302         return(-1);
304     return(0);
309 /******************************************************************************
310  * Function:    Send a maintenance packet
311  ******************************************************************************/
312 void
313 mainPacket
315     uint32_t    addr,
316     uint32_t    value
319     volatile uint32_t vx;
320     uint32_t busy, count;
322     value = swap(value);
324     /* Claim the LSU */
325     vx = DEVICE_REG32_R(0x2900d18);
327     /* Program a transfer on port 0 */
328     /* LSU 1 Reg 0 - MSB of destination */
329     DEVICE_REG32_W(0x2900d00, 0x00000000);
332     /* LSU 1 Reg 1 - LSB of destination */
333     DEVICE_REG32_W(0x2900d04, addr - 0x290b000);
335     /* LSU 1 Reg 2 - source address */
336     DEVICE_REG32_W(0x2900d08, (1 << 28) | (coreNum << 24) | (uint32_t)&value);
339     /* LSU 1 Reg 3 - Byte count */
340     DEVICE_REG32_W(0x2900d0c, 4);
342     /* LSU 1 Reg 4 -
343     * out port ID = 0
344     * Priority = 2
345     * XAM = 0
346     * ID size = 1 (16 bit)
347     * Dest ID specified as arg
348     * int32_terrupt request = 0 */
349     DEVICE_REG32_W(0x2900d10, 0xffff0000 | (port << 8));
352     /* LSU 1 Reg 5 -
353     * doorbell info = 0 for this packet type
354     * hop count = 0 for this packet type
355     * Packet type = 0x54 - ftype = 5, ttype = 4
356     *                      nwrite packet type.
357     * Writing this register should initiate the transfer */
358     /*  *((uint32_t *)0x2900d14) = 0x00000054;  */
359     DEVICE_REG32_W(0x2900d14, 0x00000081);  /* maint32_tenance write */
361     /* wait for it to complete */
362     count = 0;
363     do{
364         platform_delay(1);
365         count++;
366         if (count >= WAIT_TIMEOUT)
367         {
368             printf("Send a maintenance packet failed\n");
369             return;
370         }
371         busy = DEVICE_REG32_R(0x2900d18);
373     } while ((busy & 0x80000000) != 0x00000000);
375     return;
378 /* Return if Port is OK or not */
379 int32_t SRIOPortStatus(uint32_t port_num)
381     uint32_t count,value,portok;
383     count = 0;
384     portok= 0;
386     while(1)
387     {
388         value = DEVICE_REG32_R(SRIO_PORT_ERR_STATUS_REG(port_num));
390         if((value & 0x02) !=0)
391         {
392             portok++;
393             if(portok >= 50)
394             {
395                 break; /* port must be solid OK */
396             }
397         }
398         else
399         {
400             portok = 0;
401             count++;
402             if (count >= WAIT_TIMEOUT)
403             {
404                 return(-1);
405             }
406         }
407         platform_delay(1);
408     }
410     return(0);
413 void
414 srio_init
416     uint32_t    port_num,
417     uint32_t    loopback
420     /* Enable the Transmit register */
421     DEVICE_REG32_W(0x290b13c, 0x40000000);
423     if (loopback)
424     {
425         /* Enable Lane loop back for all the ports */
426         DEVICE_REG32_W(0x2900018, 0x000000f0);
427     }
429     /* check for the port status */
430     if (SRIOPortStatus(port_num) != 0)
431     {
432         printf("Port %d is not OK!\n", port_num);
433     }
435     /* TLM SP0 control, enable promiscuous mode */
436     mainPacket (0x291b380, 0x00309000);
438     mainPacket (0x290b15c, 0x00600000);
441 void main (void)
443     platform_init_flags     init_flags;
444     platform_init_config    init_config;
445     char                    version_msg[] = "\r\n\r\nSRIO Boot Host Example Version ";
447     printf("%s%s\n\n", version_msg, version);
449     /* Initialize main Platform lib */
450     memset(&init_config, 0, sizeof(platform_init_config));
451     memset(&init_flags, 1, sizeof(platform_init_flags));
452     if (platform_init(&init_flags, &init_config) != Platform_EOK)
453     {
454         printf ("Platform init failed!\n");
455         print_platform_errno();
456         return;
457     }
459     coreNum = platform_get_coreid();
461     /* Init port 0, disable loopback */
462     srio_init(port, loopback);
464     /* Push the DDR init code to remote DSP core 0 and boot core 0 to initialize the DDR */
465     if(pushData2Srio(ddrInitCode, rio_id)==0)
466     {
467         printf("Transfer DDR init code via SRIO successfully\n");
469         platform_delay(100000);
471         /* Push the boot image code to remote DSP DDR and boot core 0 to run Hello World */
472         if(pushData2Srio(bootCode, rio_id)==0)
473         {
474             printf("Transfer boot code via SRIO successfully\n");
475         }
476         else
477         {
478             printf("DSP boot failed.\n");
479         }
480     }
481     else
482     {
483         printf("DSP boot failed.\n");
484     }
486     for (;;);