]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/hal/arm/mx37/stk5/v1_0/src/tx37_misc.c
RedBoot TX53 Release 2012-02-15
[karo-tx-redboot.git] / packages / hal / arm / mx37 / stk5 / v1_0 / src / tx37_misc.c
1 //==========================================================================
2 //
3 //              tx37_misc.c
4 //
5 //              HAL misc board support code for the TX37 board
6 //
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12 //
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
16 //
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20 // for more details.
21 //
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25 //
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
32 //
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
35 //
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license/
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //========================================================================*/
41
42 #include <pkgconf/hal.h>
43 #include <pkgconf/system.h>
44 #include <redboot.h>
45 #include CYGBLD_HAL_PLATFORM_H
46
47 #include <cyg/infra/cyg_type.h>                 // base types
48 #include <cyg/infra/cyg_trac.h>                 // tracing macros
49 #include <cyg/infra/cyg_ass.h>                  // assertion macros
50
51 #include <cyg/hal/hal_io.h>                             // IO macros
52 #include <cyg/hal/hal_arch.h>                   // Register state info
53 #include <cyg/hal/hal_diag.h>
54 #include <cyg/hal/hal_intr.h>                   // Interrupt names
55 #include <cyg/hal/hal_cache.h>
56 #include <cyg/hal/hal_soc.h>             // Hardware definitions
57 #include <cyg/hal/karo_tx37.h>                     // Platform specifics
58 //#include <cyg/io/mxc_i2c.h>
59 #include <cyg/infra/diag.h>                             // diag_printf
60
61 // All the MM table layout is here:
62 #include <cyg/hal/hal_mm.h>
63
64 externC void* memset(void *, int, size_t);
65
66 volatile void *gpio_mcu1 = (volatile void *)GPIO1_BASE_ADDR;
67 volatile void *gpio_mcu2 = (volatile void *)GPIO2_BASE_ADDR;
68 volatile void *gpio_mcu3 = (volatile void *)GPIO3_BASE_ADDR;
69 volatile void *iomux = (volatile void *)IOMUXC_BASE_ADDR;
70
71 /* point to Data Direction Registers (DDIR) of all GPIO ports */
72 static volatile cyg_uint32 *const data_dir_reg_ptr_array[3] = {
73         (cyg_uint32 *) ((cyg_uint32) GPIO1_BASE_ADDR + 4),
74         (cyg_uint32 *) ((cyg_uint32) GPIO1_BASE_ADDR + 4),
75         (cyg_uint32 *) ((cyg_uint32) GPIO1_BASE_ADDR + 4)
76 };
77
78 /* point to Data Registers (DR) of all GPIO ports */
79 static volatile unsigned int *const data_reg_ptr_array[3] = {
80         (cyg_uint32 *) GPIO1_BASE_ADDR,
81         (cyg_uint32 *) GPIO2_BASE_ADDR,
82         (cyg_uint32 *) GPIO3_BASE_ADDR
83 };
84
85 /* point to Pad Status Registers (PSR) of all GPIO ports */
86 static volatile unsigned int *const pad_status_reg_ptr_array[3] = {
87         (cyg_uint32 *) ((cyg_uint32) GPIO1_BASE_ADDR + 4 * 2),
88         (cyg_uint32 *) ((cyg_uint32) GPIO2_BASE_ADDR + 4 * 2),
89         (cyg_uint32 *) ((cyg_uint32) GPIO3_BASE_ADDR + 4 * 2)
90 };
91
92 /* point to IOMUX SW MUX Control Registers*/
93 static volatile unsigned int *const iomux_sw_mux_ctrl_reg_array[3] = {
94         (cyg_uint32 *) ((cyg_uint32) IOMUXC_BASE_ADDR + 0x0008),        //the offset of sw_mux_ctrl_reg_array is 0x0004
95         (cyg_uint32 *) ((cyg_uint32) IOMUXC_BASE_ADDR + 0x0230),        //the offset of sw_pad_ctrl_reg_array is 0x0328
96         (cyg_uint32 *) ((cyg_uint32) IOMUXC_BASE_ADDR + 0x0508),        //the offset of daisy_sel_in_reg_array is 0x07AC
97 };
98
99 #if 1
100 #define UARO_URXD       0x00
101 #define UARO_UTXD       0x40
102 #define UARO_UCR1       0x80
103 #define UARO_UCR2       0x84
104 #define UARO_UCR3       0x88
105 #define UARO_UCR4       0x8c
106 #define UARO_UFCR       0x90
107 #define UARO_USR1       0x94
108 #define UARO_USR2       0x98
109 #define UARO_UESC       0x9c
110 #define UARO_UTIM       0xa0
111 #define UARO_UBIR       0xa4
112 #define UARO_UBMR       0xa8
113 #define UARO_UBRC       0xac
114 #define UARO_ONEMS      0xb0
115 #define UARO_UTS        0xb4
116
117 void plf_uart_init(void)
118 {
119         unsigned long val;
120         unsigned long UartRefFreq;
121
122         // UART1
123         //RXD
124         writel(0x0, IOMUXC_BASE_ADDR + 0x15C);
125         writel(0x4, IOMUXC_BASE_ADDR + 0x604);
126         writel(0x1C5, IOMUXC_BASE_ADDR + 0x3BC);
127
128         //TXD
129         writel(0x0, IOMUXC_BASE_ADDR + 0x160);
130         writel(0x1C5, IOMUXC_BASE_ADDR + 0x3C0);
131
132         //RTS
133         writel(0x0, IOMUXC_BASE_ADDR + 0x164);
134         writel(0x4, IOMUXC_BASE_ADDR + 0x600);
135         writel(0x1C4, IOMUXC_BASE_ADDR + 0x3C4);
136
137         //CTS
138         writel(0x0, IOMUXC_BASE_ADDR + 0x168);
139         writel(0x1C4, IOMUXC_BASE_ADDR + 0x3C8);
140
141         /* Wait for UART to finish transmitting */
142         while (!(readl(UART1_BASE_ADDR + UARO_UTS) & 0x40));
143
144         /* Disable UART */
145         val = readl(UART1_BASE_ADDR + UARO_UCR1); 
146         writel(val & 0xfffffffe, UART1_BASE_ADDR + UARO_UCR1); /* reset UARTEN */
147
148         /* Set to default POR state */
149         writel(0x00000000, UART1_BASE_ADDR + UARO_UCR1);
150         writel(0x00000000, UART1_BASE_ADDR + UARO_UCR2);
151
152         while (!(readl(UART1_BASE_ADDR + UARO_UCR2) & 1));              /* wait for SRST = 1 */
153
154         writel(0x00000704, UART1_BASE_ADDR + UARO_UCR3);
155         writel(0x00008000, UART1_BASE_ADDR + UARO_UCR4);
156         writel(0x00000801, UART1_BASE_ADDR + UARO_UFCR);
157         writel(0x0000002B, UART1_BASE_ADDR + UARO_UESC);
158         writel(0x00000000, UART1_BASE_ADDR + UARO_UTIM);
159         writel(0x00000000, UART1_BASE_ADDR + UARO_UBIR);
160         writel(0x00000000, UART1_BASE_ADDR + UARO_UBMR);
161         writel(0x00000000, UART1_BASE_ADDR + UARO_ONEMS);
162         writel(0x00000000, UART1_BASE_ADDR + UARO_UTS);
163
164         /* Configure FIFOs */
165         writel((1 << 0) | (4 << 7) | (2 << 10), UART1_BASE_ADDR + UARO_UFCR);
166         UartRefFreq = 66500000 / 2;
167
168         /* Setup One MS timer */
169         writel((UartRefFreq / 1000), UART1_BASE_ADDR + UARO_ONEMS);
170
171         /* Set to 8N1 */
172         val = readl(UART1_BASE_ADDR + UARO_UCR2); 
173         val &= ~(1 << 8);
174         val |= (1 << 5);
175         val |= (1 << 14); /* Ignore RTS */
176         val &= ~(1 << 6);
177         writel(val, UART1_BASE_ADDR + UARO_UCR2); 
178
179         /* Enable UART */
180         val = readl(UART1_BASE_ADDR + UARO_UCR1); 
181         writel(val | 1, UART1_BASE_ADDR + UARO_UCR1); 
182
183         /* Enable FIFOs */
184         val = readl(UART1_BASE_ADDR + UARO_UCR2); 
185         val |= (1 << 0);
186         val |= (1 << 1);
187         val |= (1 << 2);
188         writel(val, UART1_BASE_ADDR + UARO_UCR2); 
189
190         /* Clear status flags */
191         val = readl(UART1_BASE_ADDR + UARO_USR2); 
192         val |= 0x9197;
193         writel(val, UART1_BASE_ADDR + UARO_USR2); 
194
195         /* Clear status flags */
196         val = readl(UART1_BASE_ADDR + UARO_USR1); 
197         val |= 0x9c30;
198         writel(val, UART1_BASE_ADDR + UARO_USR1); 
199
200         /* Set the numerator value minus one of the BRM ratio */
201         writel((115200 / 100) - 1, UART1_BASE_ADDR + UARO_UBIR);
202
203         /* Set the denominator value minus one of the BRM ratio    */
204         writel((UartRefFreq / 1600) - 1, UART1_BASE_ADDR + UARO_UBMR);
205
206         writel('+', UART1_BASE_ADDR + UARO_UTXD);
207 }
208
209 void plf_send_char(unsigned char c)
210 {
211         /* Wait for UART to finish transmitting */
212         while (!(readl(UART1_BASE_ADDR + UARO_UTS) & 0x40));
213
214         writel(c, UART1_BASE_ADDR + UARO_UTXD);
215 }
216
217 void plf_send_string(const char *spt)
218 {
219         unsigned char achar;
220
221         while ((achar = *(spt++)) != '\0') {
222                 plf_send_char(achar);
223         }
224 }
225
226 void plf_printhex(unsigned long val)
227 {
228         int i;
229
230         for (i = 28; i >= 0; i -= 4) {
231                 int digit = (val >> i) & 0xf;
232                 plf_send_char(digit + ((digit < 10) ? '0' : ('A' - 10)));
233         }
234 }
235
236 void plf_dumpmem(unsigned long addr, int len)
237 {
238         int i;
239
240         for (i = 0; i < len; i += 4) {
241                 unsigned long *wp = (unsigned long *)(addr + i);
242                 if (i % 16 == 0) {
243                         plf_send_char('\r');
244                         plf_send_char('\n');
245                         plf_printhex(addr + i);
246                         plf_send_char(' ');
247                 }
248                 plf_printhex(*wp);
249                 plf_send_char(' ');
250         }
251         if (i % 16 == 0) {
252                 plf_send_char('\r');
253                 plf_send_char('\n');
254         }
255 }
256
257 void hal_mmu_check(void)
258 {
259         unsigned long cr0, cr1;
260
261         asm volatile ("mrc      p15, 0, %0, c1, c0, 0" : "=r"(cr0) /*:*/);
262         asm volatile ("mrc      p15, 0, %0, c1, c0, 1" : "=r"(cr1) /*:*/);
263         plf_printhex(cr0);
264         plf_send_char(' ');
265         plf_printhex(cr1);
266         plf_send_char('\r');
267         plf_send_char('\n');
268 }
269
270 #define DBG_FUNC() do {                         \
271         plf_send_string(__FUNCTION__);          \
272         plf_send_char('\r');                    \
273         plf_send_char('\n');                    \
274         } while (0)
275 #endif
276
277 void hal_mmu_init(void)
278 {
279         unsigned long ttb_base = RAM_BANK0_BASE + 0x4000;
280         unsigned long i;
281 #ifdef DEBUG
282         plf_uart_init();
283         DBG_FUNC();
284         hal_mmu_check();
285 #endif
286         /*
287          * Set the TTB register
288          */
289         asm volatile ("mcr      p15, 0, %0, c2, c0, 0" : : "r"(ttb_base) /*:*/);
290
291         /*
292          * Set the Domain Access Control Register
293          */
294         i = ARM_ACCESS_DACR_DEFAULT;
295         asm volatile ("mcr      p15, 0, %0, c3, c0, 0" : : "r"(i) /*:*/);
296
297         /*
298          * First clear all TT entries - ie Set them to Faulting
299          */
300         memset((void *)ttb_base, 0, ARM_FIRST_LEVEL_PAGE_TABLE_SIZE);
301
302         /*           Physical Virtual   Size   Attributes                                                    Function */
303         /*           Base     Base      MB     cached?          buffered?         access permissions                  */
304         /*           xxx00000 xxx00000                                                                                */
305         X_ARM_MMU_SECTION(0x000, 0x200, 0x200, ARM_UNCACHEABLE, ARM_UNBUFFERABLE, ARM_ACCESS_PERM_RW_RW); /* ROM */
306         X_ARM_MMU_SECTION(0x100, 0x100, 0x001, ARM_UNCACHEABLE, ARM_UNBUFFERABLE, ARM_ACCESS_PERM_RW_RW); /* IRAM */
307         X_ARM_MMU_SECTION(0x400, 0x000, TX37_SDRAM_SIZE >> 20, ARM_CACHEABLE,   ARM_BUFFERABLE,   ARM_ACCESS_PERM_RW_RW); /* SDRAM */
308         X_ARM_MMU_SECTION(0x400, 0x400, TX37_SDRAM_SIZE >> 20, ARM_CACHEABLE,   ARM_BUFFERABLE,   ARM_ACCESS_PERM_RW_RW); /* SDRAM */
309         X_ARM_MMU_SECTION(0x7ff, 0x7ff, 0x001, ARM_UNCACHEABLE, ARM_UNBUFFERABLE, ARM_ACCESS_PERM_RW_RW); /* NAND Flash buffer */
310         X_ARM_MMU_SECTION(0x800, 0x800, 0x020, ARM_UNCACHEABLE, ARM_UNBUFFERABLE, ARM_ACCESS_PERM_RW_RW); /* IPUv3D */
311         X_ARM_MMU_SECTION(0xB00, 0xB00, 0x400, ARM_UNCACHEABLE, ARM_UNBUFFERABLE, ARM_ACCESS_PERM_RW_RW); /* periperals */
312
313 #ifdef DEBUG
314 #if 1
315         plf_printhex(ttb_base);
316         plf_send_char('\r');
317         plf_send_char('\n');
318 #endif
319 #if 0
320         plf_dumpmem(ttb_base, ARM_FIRST_LEVEL_PAGE_TABLE_SIZE);
321 #endif
322 #if 1
323         plf_dumpmem(0xc3fa8000, 0x1000);
324 #endif
325 #if 0
326         plf_dumpmem(0xc3fa8000, 0x1000);
327         plf_dumpmem(0xc3fa8000, 0x1000);
328         plf_dumpmem(0xc3fa8000, 0x1000);
329 #endif
330 #endif
331 }
332
333 //
334 // Platform specific initialization
335 //
336
337 void plf_hardware_init(void)
338 {
339         unsigned int v;
340
341 #ifdef DEBUG
342         DBG_FUNC();
343         hal_mmu_check();
344 #endif
345         v = 0x0040174A; // modified
346         writel(v, NFC_FLASH_CONFIG2_REG);
347
348         writel(0xFFFF0000, UNLOCK_BLK_ADD0_REG);
349         writel(0xFFFF0000, UNLOCK_BLK_ADD1_REG);
350         writel(0xFFFF0000, UNLOCK_BLK_ADD2_REG);
351         writel(0xFFFF0000, UNLOCK_BLK_ADD3_REG);
352
353         v = NFC_WR_PROT_CS0 | NFC_WR_PROT_BLS_UNLOCK | NFC_WR_PROT_WPC;
354         writel(v, NFC_WR_PROT_REG);
355
356         writel(0, NFC_IPC_REG);
357 #if 0
358         /* PBC setup */
359         //Enable UART transceivers also reset the Ethernet/external UART
360         temp = readw(PBC_BASE + PBC_BCTRL1);
361
362         writew(0x8023, PBC_BASE + PBC_BCTRL1);
363
364         for (i = 0; i < 100000; i++) {
365         }
366
367         // clear the reset, toggle the LEDs
368         writew(0xDF, PBC_BASE + PBC_BCTRL1_CLR);
369
370         for (i = 0; i < 100000; i++) {
371         }
372
373         dummy = readb(0xB4000008);
374         dummy = readb(0xB4000007);
375         dummy = readb(0xB4000008);
376         dummy = readb(0xB4000007);
377 #endif
378
379 #if 0
380         /* Reset interrupt status reg */
381         writew(0x1F, PBC_INT_REST);
382         writew(0x00, PBC_INT_REST);
383         writew(0xFFFF, PBC_INT_MASK);
384 #endif
385         // UART1
386         //RXD
387         writel(0x0, IOMUXC_BASE_ADDR + 0x15C);
388         writel(0x4, IOMUXC_BASE_ADDR + 0x604);
389         writel(0x1C5, IOMUXC_BASE_ADDR + 0x3BC);
390
391         //TXD
392         writel(0x0, IOMUXC_BASE_ADDR + 0x160);
393         writel(0x1C5, IOMUXC_BASE_ADDR + 0x3C0);
394
395         //RTS
396         writel(0x0, IOMUXC_BASE_ADDR + 0x164);
397         writel(0x4, IOMUXC_BASE_ADDR + 0x600);
398         writel(0x1C4, IOMUXC_BASE_ADDR + 0x3C4);
399
400         //CTS
401         writel(0x0, IOMUXC_BASE_ADDR + 0x168);
402         writel(0x1C4, IOMUXC_BASE_ADDR + 0x3C8);
403 }
404
405 #if 0
406 static void configure_gpio(cyg_uint32 port, cyg_uint32 pin,
407                            cyg_uint32 io_select, cyg_uint32 dir)
408 {
409         cyg_uint32 tmp, rnum, roffset, cfg_val;
410
411         if ((io_select & 0x200) == 0x200) {
412                 rnum = (io_select >> 12) & 0xff;
413                 roffset = (io_select >> 10) & 0x3;
414                 cfg_val = (io_select & 0xff);
415                 tmp = iomux_sw_mux_ctrl_reg_array[port][rnum];
416                 tmp &= ~(0xff << (roffset * 8));
417                 tmp |= (cfg_val << (roffset * 8));
418                 iomux_sw_mux_ctrl_reg_array[port][rnum] = tmp;
419         }
420         if ((io_select & 0x100) == 0x100) {
421                 /* Configure the direction of GPIO */
422                 if (dir) {
423                         *data_dir_reg_ptr_array[port] |= (1 << pin);
424                 } else {
425                         *data_dir_reg_ptr_array[port] &= ~(1 << pin);
426                 }
427         }
428 }
429
430 static void configure_pad(cyg_uint32 port, cyg_uint32 reg_index, cyg_uint32 val)
431 {
432         iomux_sw_mux_ctrl_reg_array[port][reg_index] = val;
433 }
434 #endif
435
436 #include CYGHWR_MEMORY_LAYOUT_H
437
438 typedef void code_fun(void);
439
440 void board_program_new_stack(void *func)
441 {
442         register CYG_ADDRESS stack_ptr asm("sp");
443         register CYG_ADDRESS old_stack asm("r4");
444         register code_fun *new_func asm("r0");
445         old_stack = stack_ptr;
446         stack_ptr = CYGMEM_REGION_ram + CYGMEM_REGION_ram_SIZE - sizeof(CYG_ADDRESS);
447         new_func = (code_fun*)func;
448         new_func();
449         stack_ptr = old_stack;
450 }
451
452 #define SRC_SRSR 0x08
453
454 static void display_board_info(void)
455 {
456         char *reset_cause = "UNKNOWN";
457         CYG_WORD32 srsr;
458
459         DBG_FUNC();
460         diag_printf("\nBoard Type: Ka-Ro TX37\n");
461
462         HAL_READ_UINT32(SRC_BASE_ADDR + SRC_SRSR, srsr);
463         switch (srsr) {
464         case (1 << 0):
465                 reset_cause = "POWER_ON RESET";
466                 break;
467         case (1 << 2):
468                 reset_cause = "EXTERNAL RESET";
469                 break;
470         case (1 << 3):
471                 reset_cause = "COLD RESET";
472                 break;
473         case (1 << 4):
474                 reset_cause = "WATCHDOG RESET";
475                 break;
476         case (1 << 5):
477                 reset_cause = "JTAG RESET";
478                 break;
479         case (1 << 16):
480                 reset_cause = "SOFT RESET";
481                 break;
482         }
483
484         diag_printf("Last RESET cause: %s\n", reset_cause);
485 }
486
487 RedBoot_init(display_board_info, RedBoot_INIT_LAST);