import of upstream version 1.16
[mw/micromonitor-lm32.git] / umon_ports / bf537 / mode7boot.c
1 #define __ADSPLPBLACKFIN__
2
3 #include "cpu.h"
4 #include "cdefBF537.h"
5
6 typedef unsigned char uchar;
7 typedef unsigned short ushort;
8 typedef unsigned long ulong;
9
10 struct xinfo {
11         uchar   sno;                    /* Sequence number. */
12         uchar   pad;                    /* Unused, padding. */
13         int             xfertot;                /* Running total of transfer. */
14         int             pktcnt;                 /* Running tally of number of packets processed. */
15         long    size;                   /* Size of upload. */
16         ulong   base;                   /* Starting address for data transfer. */
17         ulong   dataddr;                /* Running address for data transfer. */
18 };
19
20 /* X/Ymodem protocol: */
21 #define SOH                     0x01
22 #define STX                     0x02
23 #define EOT                     0x04
24 #define ACK                     0x06
25 #define XNAK            0x15
26 #define CAN                     0x18
27 #define EOF                     0x1a
28 #define ESC                     0x1b
29 #define NAK_DELAY       1500000
30
31 #define PKTLEN          128
32 #define ENTRY           BASE
33
34 void Go(void);
35 int Xdown(void);
36 int getPacket(uchar *,struct xinfo *);
37
38 long MonStack[32];
39
40 void
41 ledtoggle(void)
42 {
43         volatile int i;
44
45         *pPORTFIO_SET |= LED_BITMASK;
46         for(i=0;i<9000000;i++);
47         *pPORTFIO_CLEAR |= LED_BITMASK;
48         for(i=0;i<5000000;i++);
49 }
50
51 /* devInit():
52  * Initialize console...
53  */
54 void
55 devInit(int baud)
56 {
57         unsigned short tmp;
58         unsigned short  lctl, hi, lo;
59
60         *pUART0_GCTL = 1;               /* Set the UCEN bit (enable UART clocks) */
61         *pUART0_MCR = 0;
62         *pUART0_LCR = 0x03;
63         tmp = *pUART0_LSR;
64         *pUART0_IER = 0;
65         *pUART0_SCR = 0;
66
67         lo = SYSCLKFREQ/(baud*16);
68         hi = (lo & 0xff00) >> 8;
69         lo &= 0x00ff;
70
71         lctl = *pUART0_LCR;
72         *pUART0_LCR = DLAB;
73         *pUART0_DLL = lo;
74         *pUART0_DLH = hi;
75         *pUART0_LCR = lctl;
76 }
77
78 /* target_putchar():
79  * When buffer has space available, load the incoming character
80  * into the UART.
81  */
82 int
83 target_putchar(char c)
84 {
85     /* Wait for transmit ready bit */
86         while(!(*pUART0_LSR & THRE));
87
88         *pUART0_THR = (unsigned short)c;
89
90     return((int)c);
91 }
92
93 int
94 target_gotachar(void)
95 {
96         if (*pUART0_LSR & DR)
97                 return(1);
98     return(0);
99 }
100  
101 int 
102 target_getchar(void)
103 {
104     return((int)*pUART0_RBR);
105 }
106
107 int
108 getchar(void)
109 {
110         while((*pUART0_LSR & DR) == 0);
111     return((int)*pUART0_RBR);
112 }
113
114 void
115 memtest(void)
116 {
117         volatile long i, *lp;
118
119         lp = (volatile long *)BASE;
120
121         for(i=0;i<(1024*256);i++) {
122                 *lp = i;
123         }
124         for(i=0;i<(1024*256);i++) {
125                 if (*lp != i) {
126                         target_putchar('F');
127                         return;
128                 }
129         }
130         target_putchar('P');
131 }
132
133 void
134 mode7start(void)
135 {
136         int xdone;
137         volatile char *cp;
138         volatile int c;
139         volatile unsigned short stmp;
140         volatile unsigned long ltmp;
141
142         /* PLL setup:
143          */
144         asm("ssync;");
145         *pPLL_CTL = (MSEL_VAL << 9) | PLL_DF_VAL;
146         *pSIC_IWR = 1;
147         asm("ssync;");
148         asm("cli r0;");
149         asm("idle;");
150         asm("sti r0;");
151         asm("ssync;");
152
153         *pPLL_LOCKCNT = 0x0300;
154         *pPLL_DIV = (SSEL_VAL) | (CSEL_VAL << 4);
155         asm("ssync;");
156
157         *pDTEST_COMMAND = 0;
158
159         /* Memory bank init:
160          */
161         *pEBIU_AMBCTL0 = 0x7bb07bb0;
162         *pEBIU_AMBCTL1 = 0xffc27bb0;
163         asm("ssync;");
164
165         /* SDRAM ctrlr init:
166          * (should be done 100us after reset)
167          * Refer to pg 6-60 of HW reference.
168          */
169         for(c=0;c<10000000;c++);
170         *pEBIU_SDRRC = (((SYSCLKFREQ/1000) * 64) / 8192) - (TRAS + TRP);
171         asm("ssync;");
172         *pEBIU_SDBCTL = (EBCAW_10 | EBSZ_64 | EBE);
173         asm("ssync;");
174         if (*pEBIU_SDSTAT & SDRS)
175                 *pEBIU_SDGCTL = (PSS | TWR_2 | TRCD_2 | TRP_2 | TRAS_5 | CL_3 | SCTLE);
176         else
177                 *pEBIU_SDGCTL = (TWR_2 | TRCD_2 | TRP_2 | TRAS_5 | CL_3 | SCTLE);
178         asm("ssync;");
179
180         *pEBIU_AMGCTL = 0x00ff;
181         asm("ssync;");
182         
183         for(c=0;c<10000;c++);
184                 *(char *)c = (char)c;
185
186         *pPORT_MUX = 0x0000;
187
188         /* Port F configuration:
189          */
190         stmp = *pPORTF_FER;
191         *pPORTF_FER = 0x000f;
192         *pPORTF_FER = 0x000f;
193         *pPORTFIO_DIR = LED_BITMASK;
194         *pPORTF_FER = 0x000f;
195         *pPORTF_FER = 0x000f;
196
197         /* Port G configuration:
198          */
199         stmp = *pPORTG_FER;
200         *pPORTG_FER = 0x0000;
201         *pPORTG_FER = 0x0000;
202
203         /* Port H configuration:
204          */
205         stmp = *pPORTH_FER;
206         *pPORTH_FER = 0xffff;
207         *pPORTH_FER = 0xffff;
208
209         devInit(DEFAULT_BAUD_RATE);
210         xdone = 0;
211         while(1) {
212                 if (target_gotachar()) {
213                         c = target_getchar();
214                         if (c == 'x') {
215                                 if (Xdown() > 0)
216                                         xdone = 1;
217                         }
218                         else if (c == 't') {
219                                 memtest();
220                         }
221                         else if (c == 'g') {
222                                 if (xdone == 1)
223                                         Go();
224                                 else
225                                         target_putchar('?');
226                         }
227                         else
228                                 target_putchar(c);
229                 }
230                 target_putchar(':');
231                 ledtoggle();
232         }
233 }
234
235 /* getPacket():
236  * Used by Xdown to retrieve packets.
237  */
238 int
239 getPacket(uchar *tmppkt, struct xinfo *xip)
240 {
241         char    *pkt;
242         int             i,rcvd;
243         uchar   csum, xcsum, seq[2];
244
245         seq[0] = getchar();
246         seq[1] = getchar();
247
248         pkt = (char *)xip->dataddr;
249         for(i=0;i<PKTLEN;i++)
250                 *pkt++ = getchar();
251         pkt = (char *)xip->dataddr;
252
253         xcsum = (uchar)getchar();
254         csum = 0;
255         for(i=0;i<PKTLEN;i++)
256                 csum += *pkt++;
257         if (csum != xcsum) {
258                 target_putchar(XNAK);
259                 return(0);
260         }
261
262         /* Test the sequence number compliment...
263          */
264         if ((uchar)seq[0] != (uchar)~seq[1]) {
265                 target_putchar(XNAK);
266                 return(0);
267         }
268
269         /* Verify that the incoming sequence number is the expected value...
270          */
271         if ((uchar)seq[0] !=  xip->sno) {
272                 /* If the incoming sequence number is one less than the expected
273                  * sequence number, then we assume that the sender did not recieve
274                  * our previous ACK, and they are resending the previously received
275                  * packet.  In that case, we send  ACK and don't process the
276                  * incoming packet...
277                  */
278                 if ((uchar)seq[0] == xip->sno-1) {
279                         target_putchar(ACK);
280                         return(0);
281                 }
282
283                 /* Otherwise, something's messed up...
284                  */
285                 target_putchar(CAN);
286                 return(-1);
287         }
288
289         xip->dataddr += PKTLEN;
290         xip->sno++;
291         xip->pktcnt++;
292         xip->xfertot += PKTLEN;
293         target_putchar(ACK);
294         return(0);
295 }
296
297 /* Xdown():
298  * Called when a transfer from host to target is being made
299  * (considered an download).
300  */
301 int
302 Xdown(void)
303 {
304         int             done = 0;
305         struct  xinfo xi;
306         char    c, *tmppkt;
307         static char pkt[PKTLEN];
308
309         tmppkt = pkt;
310         xi.size = 0;
311         xi.dataddr = xi.base = BASE;
312         xi.sno = 0x01;
313         xi.pktcnt = 0;
314         xi.xfertot = 0;
315
316         /* Startup synchronization... */
317         /* Continuously send XNAK or 'C' until sender responds. */
318         while(1) {
319                 volatile int i;
320                 target_putchar(XNAK);
321
322                 for(i=0;i<NAK_DELAY;i++) {
323                         if (target_gotachar())
324                                 break;
325                 }
326                 if (target_gotachar())
327                         break;
328         }
329
330         while(done == 0) {
331                 c = (char)getchar();
332                 if (c == SOH) {         /* 128-byte incoming packet */
333                         done = getPacket((uchar *)tmppkt,&xi);
334                 }
335                 else if (c == EOT) {
336                         target_putchar(ACK);
337                         done = xi.xfertot;
338                 }
339                 else if (c == EOF) {    /* 0x1a sent by MiniCom, just ignore it. */
340                         done = 0;
341                 }
342                 else {
343                         done = -1;
344                 }
345         }
346         return(done);
347 }
348
349 void
350 Go(void)
351 {
352         void (*entry)(void);
353
354         entry = (void(*)(void))ENTRY;
355         entry();
356 }