Created SRIO boot examples
[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 "srioBootCode.h"
39 /* Magic address RBL is polling */
40 #define BOOT_MAGIC_ADDR     0x1087fffc
42 /* Entry address of the boot image */
43 #define BOOT_ENTRY_ADDR     0xc000000
45 /* Maximum number of bytes per transfer */
46 #define MAX_TX_SIZE         1024
48 /* SRIO transfer wait timeout in usec */
49 #define WAIT_TIMEOUT        500000
51 /* SRIO Boot Example Version */
52 char version[] = "01.00.00.00";
54 uint32_t coreNum;
56 /* These can be changed on the fly during the test */
57 volatile uint32_t port      = 0;
58 volatile uint32_t rio_id    = 0;
59 volatile uint32_t loopback  = 0;
61 #pragma DATA_ALIGN(bootEntryAddr, 16)
62 volatile uint32_t bootEntryAddr = BOOT_ENTRY_ADDR;  /* Base address of MSMC */
65 /* Port error status registers */
66 uint32_t volatile *port_err_status_reg[] =  {
68     (uint32_t volatile *)0x290b158,
69     (uint32_t volatile *)0x290b178,
70     (uint32_t volatile *)0x290b198,
71     (uint32_t volatile *)0x290b1b8
72 };
75 /* Convert bytes to 32 bits */
76 uint32_t byteto32bits(uint8_t *pDspCode)
77 {
78     int32_t i;
79     uint32_t temp;
80     
81     temp = *pDspCode++;
82     for(i=0; i<3;i++) {
83         temp <<= 8;
84         temp |= *pDspCode++;
85     }
86     return(temp);
87 }
90 /* Convert to big endian, if the .out to be booted is big endian, this is not required */
91 void 
92 Convert2BigEndian
93 (
94     uint32_t    *pDspCode, 
95     int32_t     size
96 )
97 {
98     uint32_t i;
99     uint32_t temp;
100     
101     for(i=0; i<size; i+=4, pDspCode++) {
102         temp = *pDspCode;
103         
104         temp =  (temp>>24) | 
105             ((temp<<8) & 0x00FF0000) |
106             ((temp>>8) & 0x0000FF00) |
107             (temp<<24);
108         
109         *pDspCode= temp;
110     }
114 uint32_t swap (uint32_t v)
116     uint32_t w;
118     w = (((v >> 24) & 0xff) <<  0)  |
119         (((v >> 16) & 0xff) <<  8)  |
120         (((v >>  8) & 0xff) << 16)  |
121         (((v >>  0) & 0xff) << 24)  ;
123     return (w);
127 /******************************************************************************
128  * Function:    print_platform_errno
129  ******************************************************************************/
130 void
131 print_platform_errno
133     void
136     printf ("Returned platform error number is %d\n", platform_errno);
140 /*
141 Transfer (size_bytes) bytes data from host address (host_addr) to device ID's 
142 (rio_id) global address (dsp_addr). Lane 0 is used for booting.
144   rio_id:    destination device id 
145   host_addr:  host's address
146   dsp_addr:   target dsp's global address
147   size_bytes: size in bytes 
148 */
149 int SRIOTransfer(int rio_num, int port_num, unsigned int host_addr, unsigned int dsp_addr, int size_bytes)
151     unsigned int count,busy;
152     
153     /* Program a transfer on port 0 */
154     /* LSU 1 Reg 0 - MSB of destination */
155     *((volatile uint32_t *)0x2900d00) = 0x00000000;
156     
157     
158     /* LSU 1 Reg 1 - LSB of destination */
159     *((volatile uint32_t *)0x2900d04) = dsp_addr;
160     
161     
162     /* LSU 1 Reg 2 - source address */
163     *((volatile uint32_t *)0x2900d08) = (1 << 28) | (coreNum << 24) | host_addr;
164     
165     
166     /* LSU 1 Reg 3 - Byte count */
167     *((volatile uint32_t *)0x2900d0c) = size_bytes;
168     
169     
170     /* LSU 1 Reg 4 - 
171     * out port ID = 0
172     * Priority = 2
173     * XAM = 0
174     * ID size = 1 (16 bit)
175     * Dest ID specified as arg
176     * int32_terrupt request = 0 */
177     /* *((uint32_t *)0x2900d10) = 0x21000000 | (rio_id << 8)| (port << 30);  */
178     *((volatile uint32_t *)0x2900d10) = 0x00000000 | (rio_num << 8)| (port_num << 30);
179     
180     
181     /* LSU 1 Reg 5 -
182     * doorbell info = 0 for this packet type
183     * hop count = 0 for this packet type
184     * Packet type = 0x54 - ftype = 5, ttype = 4 
185     *                      nwrite packet type.
186     * Writing this register should initiate the transfer */
187     *((volatile uint32_t *)0x2900d14) = 0x00000054;
188     
189     /* wait for it to complete */
190     count = 0;
191     
192     /* wait for it to complete */
193     do{
194         platform_delay(1);
195         count++;
196         if (count >= WAIT_TIMEOUT)
197         {
198             return (-1);
199         }        busy = *((volatile uint32_t *)0x2900d18);
200         
201     } while ((busy & 0x80000000) != 0x00000000); 
202     
203     return(0);
207 /* Send boot tables to DSP and then door bell interrupt to boot the DSP
209 pDspCode: points to DSP code;
210 DeviceID: device ID.
212 */
213 int32_t bootDSP(uint8_t *pDspCode,int32_t DeviceID)
215     uint32_t i;
216     uint32_t size;
217     uint32_t count, remainder;
218     uint32_t startaddr;
219     volatile uint32_t vx;
220     
221     
222     /* Claim the LSU */
223     vx = *((volatile uint32_t *)0x2900d18);
225     /* Get the boot entry address */
226     bootEntryAddr = byteto32bits(pDspCode);
227     pDspCode +=4;
228     
229     while(1) {
230         
231         /* Get the size */
232         size =  byteto32bits(pDspCode);
233         if(size == 0) break;
234         pDspCode += 4;
235         
236         startaddr = byteto32bits(pDspCode);
237         pDspCode+= 4;
238         
239         count = size/MAX_TX_SIZE;
240         remainder = size - count * MAX_TX_SIZE;
241         
242         for(i=0; i<count; i++) {
243             /* This is not needed if the .out to be booted is big endian already */                     
244             Convert2BigEndian((uint32_t *)pDspCode,MAX_TX_SIZE);
245             
246             /* Transfer boot tables to DSP */
247             if(SRIOTransfer(rio_id, port, (uint32_t )pDspCode, (uint32_t )startaddr, MAX_TX_SIZE)!=0) return(-1);
248             pDspCode += MAX_TX_SIZE;
249             startaddr += MAX_TX_SIZE;
250         }
251         
252         /* This is not needed if the .out to be booted is big endian already */                 
253         Convert2BigEndian((uint32_t *)pDspCode,remainder);
254         
255         if(SRIOTransfer(rio_id, port,(uint32_t )pDspCode, (uint32_t )startaddr, remainder)!=0) return(-1);
256         pDspCode += remainder;
257     }
258     
259     /* Write to magic address to start booting */
260     if (SRIOTransfer(rio_id, port,(uint32_t )&bootEntryAddr, BOOT_MAGIC_ADDR, 4)!=0)
261         return(-1);
262     
263     return(0);
268 /******************************************************************************
269  * Function:    Send a maintenance packet
270  ******************************************************************************/
271 void 
272 mainPacket
274     uint32_t    addr, 
275     uint32_t    value
278     volatile uint32_t vx;
279     uint32_t busy, count;
280     
281     value = swap(value);
282     
283     /* Claim the LSU */
284     vx = *((volatile uint32_t *)0x2900d18);
285     
286     /* Program a transfer on port 0 */
287     /* LSU 1 Reg 0 - MSB of destination */
288     *((volatile uint32_t *)0x2900d00) = 0x00000000;
289     
290     
291     /* LSU 1 Reg 1 - LSB of destination */
292     *((volatile uint32_t *)0x2900d04) = addr - 0x290b000;
293     
294     /* LSU 1 Reg 2 - source address */
295     *((volatile uint32_t *)0x2900d08) = (1 << 28) | (coreNum << 24) | (uint32_t)&value;
296     
297     
298     /* LSU 1 Reg 3 - Byte count */
299     *((volatile uint32_t *)0x2900d0c) = 4;
300     
301     /* LSU 1 Reg 4 - 
302     * out port ID = 0
303     * Priority = 2
304     * XAM = 0
305     * ID size = 1 (16 bit)
306     * Dest ID specified as arg
307     * int32_terrupt request = 0 */
308     *((volatile uint32_t *)0x2900d10) = 0xffff0000 | (port << 8);
309     
310     
311     /* LSU 1 Reg 5 -
312     * doorbell info = 0 for this packet type
313     * hop count = 0 for this packet type
314     * Packet type = 0x54 - ftype = 5, ttype = 4 
315     *                      nwrite packet type.
316     * Writing this register should initiate the transfer */
317     /*  *((uint32_t *)0x2900d14) = 0x00000054;  */
318     *((volatile uint32_t *)0x2900d14) = 0x00000081;  /* maint32_tenance write */
319     
320     /* wait for it to complete */
321     count = 0;
322     do{
323         platform_delay(1);
324         count++;
325         if (count >= WAIT_TIMEOUT)
326         {
327             printf("Send a maintenance packet failed\n");
328             return;
329         }        
330         busy = *((volatile uint32_t *)0x2900d18);
331         
332     } while ((busy & 0x80000000) != 0x00000000);     
334     return;
337 /* Return if Port is OK or not */
338 int32_t SRIOPortStatus(uint32_t port_num)
340     uint32_t count,value,portok;
341     
342     count = 0;
343     portok= 0;
345     while(1)
346     {   
347         value = *port_err_status_reg[port_num];
348         
349         if((value & 0x02) !=0) 
350         {
351             portok++; 
352             if(portok >= 50) 
353             {
354                 break; /* port must be solid OK */
355             }
356         } 
357         else 
358         {
359             portok = 0;
360             count++;
361             if (count >= WAIT_TIMEOUT) 
362             {
363                 return(-1);
364             }
365         }
366         platform_delay(1);
367     }
368     
369     return(0);
372 void
373 srio_init
375     uint32_t    port_num,
376     uint32_t    loopback
379     /* Enable the Transmit register */
380     *((volatile uint32_t *)0x290b13c) = 0x40000000;
382     if (loopback)
383     {
384         /* Enable Lane loop back for all the ports */
385         *((volatile uint32_t *)0x2900018) = 0x000000f0;
386     }
388     /* check for the port status */
389     if (SRIOPortStatus(port_num) != 0)
390     {
391         printf("Port %d is not OK!\n", port_num);
392     }
394     /* TLM SP0 control, enable promiscuous mode */
395     mainPacket (0x291b380, 0x00309000);
397     mainPacket (0x290b15c, 0x00600000);
400 void main (void)
402     volatile uint32_t       vx;
403     platform_init_flags     init_flags;
404     platform_init_config    init_config;
405     char                    version_msg[] = "\r\n\r\nSRIO Boot Example Version ";
407     printf("%s%s\n\n", version_msg, version);
409     /* Initialize main Platform lib */
410     memset(&init_config, 0, sizeof(platform_init_config));
411     memset(&init_flags, 1, sizeof(platform_init_flags));
412     if (platform_init(&init_flags, &init_config) != Platform_EOK)
413     {
414         printf ("Platform init failed!\n");
415         print_platform_errno();
416         return;
417     }
419     coreNum = platform_get_coreid();
421     /* Init port 0, disable loopback */
422     srio_init(port, loopback);    
423     
424     /* Boot the DSP */
425     if(bootDSP(bootCode, rio_id)==0)
426     {
427         printf("DSP boot successful\n");
428     } 
429     else 
430     {
431         printf("DSP boot failed.\n");
432     }
433     
434     for (;;);