unified MX27, MX25, MX37 trees
[karo-tx-redboot.git] / packages / hal / arm / mx25 / karo / v1_0 / src / tx25_misc.c
1 //==========================================================================
2 //
3 //      tx25_misc.c
4 //
5 //      HAL misc board support code for the tx25
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 <stdlib.h>
43 #include <redboot.h>
44 #include <string.h>
45 #include <pkgconf/hal.h>
46 #include <pkgconf/system.h>
47 #include CYGBLD_HAL_PLATFORM_H
48
49 #include <cyg/infra/cyg_type.h>         // base types
50 #include <cyg/infra/cyg_trac.h>         // tracing macros
51 #include <cyg/infra/cyg_ass.h>          // assertion macros
52
53 #include <cyg/hal/hal_io.h>             // IO macros
54 #include <cyg/hal/hal_arch.h>           // Register state info
55 #include <cyg/hal/hal_diag.h>
56 #include <cyg/hal/hal_intr.h>           // Interrupt names
57 #include <cyg/hal/hal_cache.h>
58 #include <cyg/hal/hal_soc.h>            // Hardware definitions
59 #include <cyg/hal/karo_tx25.h>          // Platform specifics
60
61 #include <cyg/infra/diag.h>             // diag_printf
62
63 // All the MM table layout is here:
64 #include <cyg/hal/hal_mm.h>
65
66 //#define EARLY_SERIAL_SETUP
67
68 #ifdef EARLY_SERIAL_SETUP
69 static void mxc_serial_setup(void);
70
71 static void uart_putc(int c)
72 {
73         while (readl(UART1_BASE_ADDR + 0xb4) & (1 << 4)) {
74                 /* wait for !TX_FULL */
75         }
76         writel(c, UART1_BASE_ADDR + 0x40);
77 }
78
79 static void putcr(void)
80 {
81         uart_putc('\r');
82         uart_putc('\n');
83 }
84
85 static void printhex(unsigned int x, int len)
86 {
87         int i;
88
89         for (i = len - 1; i >= 0; i--) {
90                 int c = (x >> (i * 4)) & 0xf;
91                 if (c > 9) {
92                         c += 'A' - 10;
93                 } else {
94                         c += '0';
95                 }
96                 uart_putc(c);
97         }
98 }
99
100 static void dump_reg(unsigned long addr)
101 {
102         printhex(addr, 8);
103         uart_putc('=');
104         printhex(readl(addr), 8);
105         putcr();
106 }
107 #endif
108
109 #define SD_SZ           (RAM_BANK0_SIZE >> 20)
110 #define SD_B0           0x800
111 #define SD_B1           (0x800 + SD_SZ)
112 #define SD_B2           (0x880 + SD_SZ)
113 #ifdef RAM_BANK1_SIZE
114 #define SD_HI           (0x900 + ((RAM_BANK1_SIZE >> 20) - 1))
115 #endif
116
117 void hal_mmu_init(void)
118 {
119         unsigned long ttb_base = RAM_BANK0_BASE + 0x4000;
120         unsigned long i;
121
122         /*
123          * Set the TTB register
124          */
125         asm volatile ("mcr  p15, 0, %0, c2, c0, 0" : : "r"(ttb_base));
126
127         /*
128          * Set the Domain Access Control Register
129          */
130         i = ARM_ACCESS_DACR_DEFAULT;
131         asm volatile ("mcr  p15, 0, %0, c3, c0, 0" : : "r"(i));
132
133         /*
134          * First clear all TT entries - ie Set them to Faulting
135          */
136         memset((void *)ttb_base, 0, ARM_FIRST_LEVEL_PAGE_TABLE_SIZE);
137
138         /*                Phys   Virt   Size              Attributes                              Function      */
139         /*                    Base   Base   MB     cached?          buffered?         access permissions            */
140         /*                      xxx00000 */
141         X_ARM_MMU_SECTION(0x000, 0xF00, 0x001, ARM_UNCACHEABLE, ARM_UNBUFFERABLE, ARM_ACCESS_PERM_RW_RW); /* Boot Rom */
142         X_ARM_MMU_SECTION(0x43f, 0x43f, 0x3c1, ARM_UNCACHEABLE, ARM_UNBUFFERABLE, ARM_ACCESS_PERM_RW_RW); /* Internal Registers */
143         X_ARM_MMU_SECTION(0x800, 0x000, SD_SZ, ARM_CACHEABLE,   ARM_BUFFERABLE,   ARM_ACCESS_PERM_RW_RW); /* SDRAM */
144         X_ARM_MMU_SECTION(0x800, 0x800, SD_SZ, ARM_CACHEABLE,   ARM_BUFFERABLE,   ARM_ACCESS_PERM_RW_RW); /* SDRAM */
145         X_ARM_MMU_SECTION(0x800, 0x880, SD_SZ, ARM_UNCACHEABLE, ARM_UNBUFFERABLE, ARM_ACCESS_PERM_RW_RW); /* SDRAM */
146 #ifdef RAM_BANK1_SIZE
147         X_ARM_MMU_SECTION(0x900, SD_SZ, SD_SZ, ARM_CACHEABLE,   ARM_BUFFERABLE,   ARM_ACCESS_PERM_RW_RW); /* SDRAM */
148         X_ARM_MMU_SECTION(0x900, SD_B1, SD_SZ, ARM_CACHEABLE,   ARM_BUFFERABLE,   ARM_ACCESS_PERM_RW_RW); /* SDRAM */
149         X_ARM_MMU_SECTION(0x900, SD_B2, SD_SZ, ARM_UNCACHEABLE, ARM_UNBUFFERABLE, ARM_ACCESS_PERM_RW_RW); /* SDRAM */
150         /* make sure the last MiB in the upper bank of SDRAM (where RedBoot resides)
151          * has a unity mapping (required when switching MMU on) */
152         X_ARM_MMU_SECTION(SD_HI, SD_HI, 0x001, ARM_CACHEABLE,   ARM_BUFFERABLE,   ARM_ACCESS_PERM_RO_RO); /* SDRAM bank1 identity mapping */
153 #endif
154         X_ARM_MMU_SECTION(0xB20, 0xB20, 0x0E0, ARM_UNCACHEABLE, ARM_UNBUFFERABLE, ARM_ACCESS_PERM_RW_RW); /* ESDCTL, WEIM, M3IF, EMI, NFC, External I/O */
155 #ifdef EARLY_SERIAL_SETUP
156         mxc_serial_setup();
157 #endif
158 }
159
160 static inline void set_reg(unsigned long addr, CYG_WORD32 set, CYG_WORD32 clr)
161 {
162         CYG_WORD32 val;
163         HAL_READ_UINT32(addr, val);
164         val = (val & ~clr) | set;
165         HAL_WRITE_UINT32(addr, val);
166 }
167
168 //
169 // Platform specific initialization
170 //
171 static void fec_gpio_init(void)
172 {
173         /* GPIOs to set up for TX25/Starterkit-5:
174            Function       GPIO  Dir  act.  FCT
175                                      Lvl   
176            FEC_RESET      PB30  OUT  LOW   GPIO
177            FEC_ENABLE     PB27  OUT  HIGH  GPIO
178            OSCM26_ENABLE  PB22  OUT  HIGH  GPIO
179            EXT_WAKEUP     PB24  IN   HIGH  GPIO
180            FEC_TXEN       PF23  OUT  OUT   AIN
181            FEC_TXCLK      PD11  OUT  IN    AOUT
182            ...
183          */
184 #define OCR_SHIFT(bit)          (((bit) * 2) % 32)
185 #define OCR_MASK(bit)           (3 << (OCR_SHIFT(bit)))
186 #define OCR_VAL(bit,val)        (((val) << (OCR_SHIFT(bit))) & (OCR_MASK(bit)))
187 #define GPR_SHIFT(bit)          (bit)
188 #define GPR_MASK(bit)           (1 << (GPR_SHIFT(bit)))
189 #define GPR_VAL(bit,val)        (((val) << (GPR_SHIFT(bit))) & (GPR_MASK(bit)))
190 #define ICONF_SHIFT(bit)        (((bit) * 2) % 32)
191 #define ICONF_MASK(bit)         (3 << (ICONF_SHIFT(bit)))
192 #define ICONF_VAL(bit,val)      (((val) << (ICONF_SHIFT(bit))) & (ICONF_MASK(bit)))
193
194         /*
195          * make sure the ETH PHY strap pins are pulled to the right voltage
196          * before deasserting the PHY reset GPIO
197          */
198         unsigned long val;
199
200         /* FEC_TX_CLK */
201         writel(0, IOMUXC_BASE_ADDR + 0x01E8);
202         writel(0x1C0, IOMUXC_BASE_ADDR + 0x03E0);
203
204         /* FEC_RX_DV */
205         writel(0, IOMUXC_BASE_ADDR + 0x01E4);
206         writel(0x1C0, IOMUXC_BASE_ADDR + 0x03DC);
207
208         /* FEC_RDATA0 */
209         writel(0, IOMUXC_BASE_ADDR + 0x01DC);
210         writel(0x1C0, IOMUXC_BASE_ADDR + 0x03D4);
211
212         /* FEC_TDATA0 */
213         writel(0, IOMUXC_BASE_ADDR + 0x01D0);
214         writel(0x40, IOMUXC_BASE_ADDR + 0x03C8);
215
216         /* FEC_TX_EN */
217         writel(0, IOMUXC_BASE_ADDR + 0x01D8);
218         writel(0x40, IOMUXC_BASE_ADDR + 0x03D0);
219
220         /* FEC_MDC */
221         writel(0, IOMUXC_BASE_ADDR + 0x01C8);
222         writel(0x40, IOMUXC_BASE_ADDR + 0x03C0);
223
224         /* FEC_MDIO */
225         writel(0, IOMUXC_BASE_ADDR + 0x01CC);
226         writel(0x1F0, IOMUXC_BASE_ADDR + 0x03C4);
227
228         /* FEC_RDATA1 */
229         writel(0, IOMUXC_BASE_ADDR + 0x01E0);
230         writel(0x1C0, IOMUXC_BASE_ADDR + 0x03D8);
231
232         /* FEC_TDATA1 */
233         writel(0, IOMUXC_BASE_ADDR + 0x01D4);
234         writel(0x40, IOMUXC_BASE_ADDR + 0x03CC);
235
236         /* 
237          * Set up the FEC_RESET_B and FEC_ENABLE GPIO pins.
238          * Assert FEC_RESET_B, then power up the PHY by asserting
239          * FEC_ENABLE, at the same time lifting FEC_RESET_B.
240          *
241          * FEC_RESET_B: gpio4[7] is ALT 5 mode of pin D13
242          * FEC_ENABLE_B: gpio4[9] is ALT 5 mode of pin D11
243          */
244         writel(0x15, IOMUXC_BASE_ADDR + 0x0090);
245         writel(0x15, IOMUXC_BASE_ADDR + 0x0098);
246
247         writel(0x8, IOMUXC_BASE_ADDR + 0x0288); // open drain
248         writel(0x0, IOMUXC_BASE_ADDR + 0x0290); // cmos, no pu/pd
249
250         /* drop PHY power and assert reset (low) */
251         val = readl(GPIO4_BASE_ADDR + GPIO_DR) & ~((1 << 7) | (1 << 9));
252         writel(val, GPIO4_BASE_ADDR + GPIO_DR);
253
254         /* make the pins output */
255         val = readl(GPIO4_BASE_ADDR + GPIO_GDIR) | (1 << 7) | (1 << 9);
256         writel(val, GPIO4_BASE_ADDR + GPIO_GDIR);
257 }
258
259 //
260 // Platform specific initialization
261 //
262
263 unsigned int g_clock_src;
264 unsigned int g_board_type = BOARD_TYPE_TX25KARO;
265
266 static void mxc_serial_setup(void)
267 {
268         // UART1
269         /*RXD1*/
270         writel(0, IOMUXC_BASE_ADDR + 0x170);
271         writel(0x1E0, IOMUXC_BASE_ADDR + 0x368);
272
273         /*TXD1*/
274         writel(0, IOMUXC_BASE_ADDR + 0x174);
275         writel(0x40, IOMUXC_BASE_ADDR + 0x36c);
276
277         /*RTS1*/
278         writel(0, IOMUXC_BASE_ADDR + 0x178);
279         writel(0x1E0, IOMUXC_BASE_ADDR + 0x370);
280
281         /*CTS1*/
282         writel(0, IOMUXC_BASE_ADDR + 0x17c);
283         writel(0x40, IOMUXC_BASE_ADDR + 0x374);
284 }
285
286 void plf_hardware_init(void)
287 {
288         g_clock_src = FREQ_24MHZ;
289         mxc_serial_setup();
290         fec_gpio_init();
291 }
292
293 #define SOC_FBAC0_REG                   IIM_BASE_ADDR
294 #define SOC_MAC_ADDR_LOCK_BIT   2
295
296 extern int fuse_blow(int bank, int row, int bit);
297
298 int tx25_mac_addr_program(unsigned char mac_addr[ETHER_ADDR_LEN])
299 {
300         int ret = 0;
301         int i;
302
303         for (i = 0; i < ETHER_ADDR_LEN; i++) {
304                 unsigned char fuse = readl(SOC_MAC_ADDR_BASE + (i << 2));
305
306                 if ((fuse | mac_addr[i]) != mac_addr[i]) {
307                         diag_printf("MAC address fuse cannot be programmed: fuse[%d]=0x%02x -> 0x%02x\n",
308                                     i, fuse, mac_addr[i]);
309                         return -1;
310                 }
311                 if (fuse != mac_addr[i]) {
312                         ret = 1;
313                 }
314         }
315         if (ret == 0) {
316                 return ret;
317         }
318         if (readl(SOC_FBAC0_REG) & (1 << SOC_MAC_ADDR_LOCK_BIT)) {
319                 diag_printf("MAC address is locked\n");
320                 return -1;
321         }
322         for (i = 0; i < ETHER_ADDR_LEN; i++) {
323                 int bit;
324                 unsigned char fuse = readl(SOC_MAC_ADDR_BASE + (i << 2));
325
326                 for (bit = 0; bit < 8; bit++) {
327                         if (((mac_addr[i] >> bit) & 0x1) == 0)
328                                 continue;
329                         if (((mac_addr[i] >> bit) & 1) == ((fuse >> bit) & 1)) {
330                                 continue;
331                         }
332                         if (fuse_blow(0, i + ((SOC_MAC_ADDR_BASE & 0xff) >> 2), bit)) {
333                                 diag_printf("Failed to blow fuse bank 0 row %d bit %d\n",
334                                             i, bit);
335                                 ret = -1;
336                                 goto out;
337                         }
338                 }
339                 if ((fuse = readl(SOC_MAC_ADDR_BASE + (i << 2))) != mac_addr[i]) {
340                         diag_printf("Fuse[%d] verify failed; wrote: 0x%02x read: 0x%02x\n",
341                                                 i + 26, mac_addr[i], fuse);
342                         ret = -1;
343                         goto out;
344                 }
345         }
346         fuse_blow(0, 0, SOC_MAC_ADDR_LOCK_BIT);
347 out:
348         return ret;
349 }
350
351 #include CYGHWR_MEMORY_LAYOUT_H
352
353 typedef void code_fun(void);
354
355 void tx25_program_new_stack(void *func)
356 {
357         register CYG_ADDRESS stack_ptr asm("sp");
358         register CYG_ADDRESS old_stack asm("r4");
359         register code_fun *new_func asm("r0");
360         old_stack = stack_ptr;
361         stack_ptr = CYGMEM_REGION_ram + CYGMEM_REGION_ram_SIZE - sizeof(CYG_ADDRESS);
362         new_func = (code_fun*)func;
363         new_func();
364         stack_ptr = old_stack;
365 }
366
367 static void display_clock_src(void)
368 {
369         diag_printf("Clock input is 24 MHz\n");
370 }
371
372 #define WDOG_WRSR       ((CYG_WORD16 *)(WDOG_BASE_ADDR + 0x4))
373 #define CRM_RCSR        ((CYG_WORD32 *)(CCM_BASE_ADDR + 0x28))
374
375 static unsigned long random;
376 extern unsigned int hal_timer_count(void);
377 /* provide at least _some_ sort of randomness */
378 static void random_init(void)
379 {
380         do {
381                 srand(random + hal_timer_count());
382                 random = rand();
383         } while ((hal_timer_count() < 5) || (hal_timer_count() & 0x47110815));
384 }
385 RedBoot_init(random_init, RedBoot_INIT_FIRST);
386
387 static void display_board_type(void)
388 {
389         diag_printf("\nBoard Type: Ka-Ro TX25\n");
390 }
391
392 static void display_board_info(void)
393 {
394         display_board_type();
395         display_clock_src();
396 }
397 RedBoot_init(display_board_info, RedBoot_INIT_LAST);