Added platform osal malloc and free functions
[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 /* OSAL functions for Platform Library */
80 uint8_t *Osal_platformMalloc (uint32_t num_bytes, uint32_t alignment)
81 {
82         return malloc(num_bytes);
83 }
85 void Osal_platformFree (uint8_t *dataPtr, uint32_t num_bytes)
86 {
87     /* Free up the memory */
88     if (dataPtr)
89     {
90         free(dataPtr);
91     }
92 }
94 /* Convert bytes to 32 bits */
95 uint32_t byteto32bits(uint8_t *pDspCode)
96 {
97     int32_t i;
98     uint32_t temp;
100     temp = *pDspCode++;
101     for(i=0; i<3;i++) {
102         temp <<= 8;
103         temp |= *pDspCode++;
104     }
105     return(temp);
109 /* Convert to big endian, if the .out to be booted is big endian, this is not required */
110 void
111 Convert2BigEndian
113     uint32_t    *pDspCode,
114     int32_t     size
117     uint32_t i;
118     uint32_t temp;
120     for(i=0; i<size; i+=4, pDspCode++) {
121         temp = *pDspCode;
123         temp =  (temp>>24) |
124             ((temp<<8) & 0x00FF0000) |
125             ((temp>>8) & 0x0000FF00) |
126             (temp<<24);
128         *pDspCode= temp;
129     }
133 uint32_t swap (uint32_t v)
135     uint32_t w;
137     w = (((v >> 24) & 0xff) <<  0)  |
138         (((v >> 16) & 0xff) <<  8)  |
139         (((v >>  8) & 0xff) << 16)  |
140         (((v >>  0) & 0xff) << 24)  ;
142     return (w);
146 /******************************************************************************
147  * Function:    print_platform_errno
148  ******************************************************************************/
149 void
150 print_platform_errno
152     void
155     printf ("Returned platform error number is %d\n", platform_errno);
159 /*
160 Transfer (size_bytes) bytes data from host address (host_addr) to device ID's
161 (rio_id) global address (dsp_addr). Lane 0 is used for booting.
163   rio_id:    destination device id
164   host_addr:  host's address
165   dsp_addr:   target dsp's global address
166   size_bytes: size in bytes
167 */
168 int SRIOTransfer(int rio_num, int port_num, unsigned int host_addr, unsigned int dsp_addr, int size_bytes)
170     unsigned int count,busy;
172     /* Program a transfer on port 0 */
173     /* LSU 1 Reg 0 - MSB of destination */
174     DEVICE_REG32_W(0x2900d00, 0x00000000);
177     /* LSU 1 Reg 1 - LSB of destination */
178     DEVICE_REG32_W(0x2900d04, dsp_addr);
181     /* LSU 1 Reg 2 - source address */
182     DEVICE_REG32_W(0x2900d08, (1 << 28) | (coreNum << 24) | host_addr);
185     /* LSU 1 Reg 3 - Byte count */
186     DEVICE_REG32_W(0x2900d0c, size_bytes);
189     /* LSU 1 Reg 4 -
190     * out port ID = 0
191     * Priority = 2
192     * XAM = 0
193     * ID size = 1 (16 bit)
194     * Dest ID specified as arg
195     * int32_terrupt request = 0 */
196     DEVICE_REG32_W(0x2900d10, 0x00000000 | (rio_num << 8)| (port_num << 30));
199     /* LSU 1 Reg 5 -
200     * doorbell info = 0 for this packet type
201     * hop count = 0 for this packet type
202     * Packet type = 0x54 - ftype = 5, ttype = 4
203     *                      nwrite packet type.
204     * Writing this register should initiate the transfer */
205     DEVICE_REG32_W(0x2900d14, 0x00000054);
207     /* wait for it to complete */
208     count = 0;
210     /* wait for it to complete */
211     do{
212         platform_delay(1);
213         count++;
214         if (count >= WAIT_TIMEOUT)
215         {
216             return (-1);
217         }        busy = DEVICE_REG32_R(0x2900d18);
219     } while ((busy & 0x80000000) != 0x00000000);
221     return(0);
225 /* Send boot tables to DSP and then write the magic address to boot the DSP
227 pDspCode: points to DSP code;
228 DeviceID: device ID.
230 */
231 int32_t pushData2Srio(uint8_t *pDspCode,int32_t DeviceID)
233     uint32_t i;
234     uint32_t size;
235     uint32_t count, remainder;
236     uint32_t startaddr;
237     volatile uint32_t vx;
240     /* Claim the LSU */
241     vx = DEVICE_REG32_R(0x2900d18);
243     /* Get the boot entry address */
244     bootEntryAddr = byteto32bits(pDspCode);
245     pDspCode +=4;
247     while(1) {
249         /* Get the size */
250         size =  byteto32bits(pDspCode);
251         if(size == 0) break;
252         pDspCode += 4;
254         startaddr = byteto32bits(pDspCode);
255         pDspCode+= 4;
257         count = size/MAX_TX_SIZE;
258         remainder = size - count * MAX_TX_SIZE;
260         for(i=0; i<count; i++) {
261             /* This is not needed if the .out to be booted is big endian already */
262             Convert2BigEndian((uint32_t *)pDspCode,MAX_TX_SIZE);
264             /* Transfer boot tables to DSP */
265             if(SRIOTransfer(rio_id, port, (uint32_t )pDspCode, (uint32_t )startaddr, MAX_TX_SIZE)!=0) return(-1);
266             pDspCode += MAX_TX_SIZE;
267             startaddr += MAX_TX_SIZE;
268         }
270         /* This is not needed if the .out to be booted is big endian already */
271         Convert2BigEndian((uint32_t *)pDspCode,remainder);
273         if(SRIOTransfer(rio_id, port,(uint32_t )pDspCode, (uint32_t )startaddr, remainder)!=0) return(-1);
274         pDspCode += remainder;
275     }
277     /* Write to Core 0 boot magic address to boot Core 0 */
278     if (SRIOTransfer(rio_id, port,(uint32_t )&bootEntryAddr, BOOT_MAGIC_ADDR(0), 4)!=0)
279         return(-1);
281     return(0);
286 /******************************************************************************
287  * Function:    Send a maintenance packet
288  ******************************************************************************/
289 void
290 mainPacket
292     uint32_t    addr,
293     uint32_t    value
296     volatile uint32_t vx;
297     uint32_t busy, count;
299     value = swap(value);
301     /* Claim the LSU */
302     vx = DEVICE_REG32_R(0x2900d18);
304     /* Program a transfer on port 0 */
305     /* LSU 1 Reg 0 - MSB of destination */
306     DEVICE_REG32_W(0x2900d00, 0x00000000);
309     /* LSU 1 Reg 1 - LSB of destination */
310     DEVICE_REG32_W(0x2900d04, addr - 0x290b000);
312     /* LSU 1 Reg 2 - source address */
313     DEVICE_REG32_W(0x2900d08, (1 << 28) | (coreNum << 24) | (uint32_t)&value);
316     /* LSU 1 Reg 3 - Byte count */
317     DEVICE_REG32_W(0x2900d0c, 4);
319     /* LSU 1 Reg 4 -
320     * out port ID = 0
321     * Priority = 2
322     * XAM = 0
323     * ID size = 1 (16 bit)
324     * Dest ID specified as arg
325     * int32_terrupt request = 0 */
326     DEVICE_REG32_W(0x2900d10, 0xffff0000 | (port << 8));
329     /* LSU 1 Reg 5 -
330     * doorbell info = 0 for this packet type
331     * hop count = 0 for this packet type
332     * Packet type = 0x54 - ftype = 5, ttype = 4
333     *                      nwrite packet type.
334     * Writing this register should initiate the transfer */
335     /*  *((uint32_t *)0x2900d14) = 0x00000054;  */
336     DEVICE_REG32_W(0x2900d14, 0x00000081);  /* maint32_tenance write */
338     /* wait for it to complete */
339     count = 0;
340     do{
341         platform_delay(1);
342         count++;
343         if (count >= WAIT_TIMEOUT)
344         {
345             printf("Send a maintenance packet failed\n");
346             return;
347         }
348         busy = DEVICE_REG32_R(0x2900d18);
350     } while ((busy & 0x80000000) != 0x00000000);
352     return;
355 /* Return if Port is OK or not */
356 int32_t SRIOPortStatus(uint32_t port_num)
358     uint32_t count,value,portok;
360     count = 0;
361     portok= 0;
363     while(1)
364     {
365         value = DEVICE_REG32_R(SRIO_PORT_ERR_STATUS_REG(port_num));
367         if((value & 0x02) !=0)
368         {
369             portok++;
370             if(portok >= 50)
371             {
372                 break; /* port must be solid OK */
373             }
374         }
375         else
376         {
377             portok = 0;
378             count++;
379             if (count >= WAIT_TIMEOUT)
380             {
381                 return(-1);
382             }
383         }
384         platform_delay(1);
385     }
387     return(0);
390 void
391 srio_init
393     uint32_t    port_num,
394     uint32_t    loopback
397     /* Enable the Transmit register */
398     DEVICE_REG32_W(0x290b13c, 0x40000000);
400     if (loopback)
401     {
402         /* Enable Lane loop back for all the ports */
403         DEVICE_REG32_W(0x2900018, 0x000000f0);
404     }
406     /* check for the port status */
407     if (SRIOPortStatus(port_num) != 0)
408     {
409         printf("Port %d is not OK!\n", port_num);
410     }
412     /* TLM SP0 control, enable promiscuous mode */
413     mainPacket (0x291b380, 0x00309000);
415     mainPacket (0x290b15c, 0x00600000);
418 void main (void)
420     platform_init_flags     init_flags;
421     platform_init_config    init_config;
422     char                    version_msg[] = "\r\n\r\nSRIO Boot Host Example Version ";
424     printf("%s%s\n\n", version_msg, version);
426     /* Initialize main Platform lib */
427     memset(&init_config, 0, sizeof(platform_init_config));
428     memset(&init_flags, 1, sizeof(platform_init_flags));
429     if (platform_init(&init_flags, &init_config) != Platform_EOK)
430     {
431         printf ("Platform init failed!\n");
432         print_platform_errno();
433         return;
434     }
436     coreNum = platform_get_coreid();
438     /* Init port 0, disable loopback */
439     srio_init(port, loopback);
441     /* Push the DDR init code to remote DSP core 0 and boot core 0 to initialize the DDR */
442     if(pushData2Srio(ddrInitCode, rio_id)==0)
443     {
444         printf("Transfer DDR init code via SRIO successfully\n");
446         platform_delay(1000);
448         /* Push the boot image code to remote DSP DDR and boot core 0 to run Hello World */
449         if(pushData2Srio(bootCode, rio_id)==0)
450         {
451             printf("Transfer boot code via SRIO successfully\n");
452         }
453         else
454         {
455             printf("DSP boot failed.\n");
456         }
457     }
458     else
459     {
460         printf("DSP boot failed.\n");
461     }
463     for (;;);