]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/hal/arm/mx37/3stack/v2_0/src/board_misc.c
Initial revision
[karo-tx-redboot.git] / packages / hal / arm / mx37 / 3stack / v2_0 / src / board_misc.c
1 //==========================================================================
2 //
3 //      board_misc.c
4 //
5 //      HAL misc board support code for the 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/fsl_board.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 void hal_mmu_init(void)
100 {
101     unsigned long ttb_base = RAM_BANK0_BASE + 0x4000;
102     unsigned long i;
103
104     /*
105      * Set the TTB register
106      */
107     asm volatile ("mcr  p15,0,%0,c2,c0,0" : : "r"(ttb_base) /*:*/);
108
109     /*
110      * Set the Domain Access Control Register
111      */
112     i = ARM_ACCESS_DACR_DEFAULT;
113     asm volatile ("mcr  p15,0,%0,c3,c0,0" : : "r"(i) /*:*/);
114
115     /*
116      * First clear all TT entries - ie Set them to Faulting
117      */
118     memset((void *)ttb_base, 0, ARM_FIRST_LEVEL_PAGE_TABLE_SIZE);
119
120     /*              Actual   Virtual  Size   Attributes                                                    Function  */
121     /*              Base     Base     MB     cached?           buffered?        access permissions                 */
122     /*              xxx00000 xxx00000                                                                                */
123     X_ARM_MMU_SECTION(0x000, 0x200,   0x200, ARM_UNCACHEABLE, ARM_UNBUFFERABLE, ARM_ACCESS_PERM_RW_RW); /* ROM */
124     X_ARM_MMU_SECTION(0x100, 0x100,   0x001, ARM_UNCACHEABLE, ARM_UNBUFFERABLE, ARM_ACCESS_PERM_RW_RW); /* IRAM */
125     X_ARM_MMU_SECTION(0x400, 0x000,   0x080, ARM_CACHEABLE,   ARM_BUFFERABLE,   ARM_ACCESS_PERM_RW_RW); /* SDRAM */
126     X_ARM_MMU_SECTION(0x400, 0x400,   0x080, ARM_CACHEABLE,   ARM_BUFFERABLE,   ARM_ACCESS_PERM_RW_RW); /* SDRAM */
127     X_ARM_MMU_SECTION(0x7ff, 0x7ff,   0x001, ARM_UNCACHEABLE, ARM_UNBUFFERABLE, ARM_ACCESS_PERM_RW_RW); /* NAND Flash buffer */
128     X_ARM_MMU_SECTION(0x800, 0x800,   0x020, ARM_UNCACHEABLE, ARM_UNBUFFERABLE, ARM_ACCESS_PERM_RW_RW); /* IPUv3D */
129     X_ARM_MMU_SECTION(0xB00, 0xB00,   0x400, ARM_UNCACHEABLE, ARM_UNBUFFERABLE, ARM_ACCESS_PERM_RW_RW); /* periperals */
130 }
131
132 //
133 // Platform specific initialization
134 //
135
136 void plf_hardware_init(void)
137 {
138     unsigned int v;
139
140     v = 0x0040174A; // modified
141     writel(v, NFC_FLASH_CONFIG2_REG);
142
143     writel(0xFFFF0000, UNLOCK_BLK_ADD0_REG);
144     writel(0xFFFF0000, UNLOCK_BLK_ADD1_REG);
145     writel(0xFFFF0000, UNLOCK_BLK_ADD2_REG);
146     writel(0xFFFF0000, UNLOCK_BLK_ADD3_REG);
147
148     v = NFC_WR_PROT_CS0 | NFC_WR_PROT_BLS_UNLOCK | NFC_WR_PROT_WPC;
149     writel(v, NFC_WR_PROT_REG);
150
151     writel(0, NFC_IPC_REG);
152
153 #if 0
154     /* PBC setup */
155     //Enable UART transceivers also reset the Ethernet/external UART
156     temp = readw(PBC_BASE + PBC_BCTRL1);
157
158     writew(0x8023, PBC_BASE + PBC_BCTRL1);
159
160     for (i = 0; i < 100000; i++) {
161     }
162
163     // clear the reset, toggle the LEDs
164     writew(0xDF, PBC_BASE + PBC_BCTRL1_CLR);
165
166     for (i = 0; i < 100000; i++) {
167     }
168
169     dummy = readb(0xB4000008);
170     dummy = readb(0xB4000007);
171     dummy = readb(0xB4000008);
172     dummy = readb(0xB4000007);
173 #endif
174
175 #if 0
176     /* Reset interrupt status reg */
177     writew(0x1F, PBC_INT_REST);
178     writew(0x00, PBC_INT_REST);
179     writew(0xFFFF, PBC_INT_MASK);
180 #endif
181     // UART1
182     //RXD
183     writel(0x0, IOMUXC_BASE_ADDR + 0x15C);
184     writel(0x4, IOMUXC_BASE_ADDR + 0x604);
185     writel(0x1C5, IOMUXC_BASE_ADDR + 0x3BC);
186
187     //TXD
188     writel(0x0, IOMUXC_BASE_ADDR + 0x160);
189     writel(0x1C5, IOMUXC_BASE_ADDR + 0x3C0);
190
191     //RTS
192     writel(0x0, IOMUXC_BASE_ADDR + 0x164);
193     writel(0x4, IOMUXC_BASE_ADDR + 0x600);
194     writel(0x1C4, IOMUXC_BASE_ADDR + 0x3C4);
195
196     //CTS
197     writel(0x0, IOMUXC_BASE_ADDR + 0x168);
198     writel(0x1C4, IOMUXC_BASE_ADDR + 0x3C8);
199 }
200
201 static void configure_gpio(cyg_uint32 port, cyg_uint32 pin,
202                                               cyg_uint32 io_select, cyg_uint32 dir)
203 {
204     cyg_uint32 tmp, rnum, roffset, cfg_val;
205
206     if ((io_select & 0x200) == 0x200) {
207         rnum = (io_select >> 12) & 0xff;
208         roffset = (io_select >> 10) & 0x3;
209         cfg_val = (io_select & 0xff);
210         tmp = iomux_sw_mux_ctrl_reg_array[port][rnum];
211         tmp &= ~(0xff << (roffset * 8));
212         tmp |= (cfg_val << (roffset * 8));
213         iomux_sw_mux_ctrl_reg_array[port][rnum] = tmp;
214     }
215     if ((io_select & 0x100) == 0x100) {
216         /* Configure the direction of GPIO */
217         if (dir) {
218             *data_dir_reg_ptr_array[port] |= (1 << pin);
219         } else {
220             *data_dir_reg_ptr_array[port] &= ~(1 << pin);
221         }
222     }
223 }
224
225 static void configure_pad(cyg_uint32 port, cyg_uint32 reg_index, cyg_uint32 val)
226 {
227     iomux_sw_mux_ctrl_reg_array[port][reg_index] = val;
228 }
229
230 void mxc_mmc_init(base_address)
231 {
232     configure_gpio(IOMUX_SD1_CMD_PORT, IOMUX_SD1_CMD_PIN,
233                               IOMUX_SD1_CMD_SEL, IOMUX_SD1_CMD_DIR);
234     configure_gpio(IOMUX_SD1_CLK_PORT, IOMUX_SD1_CLK_PIN,
235                               IOMUX_SD1_CLK_SEL, IOMUX_SD1_CLK_DIR);
236     configure_gpio(IOMUX_SD1_DATA0_PORT,
237                               IOMUX_SD1_DATA0_PIN, IOMUX_SD1_DATA0_SEL,
238                               IOMUX_SD1_DATA0_DIR);
239     configure_gpio(IOMUX_SD1_DATA1_PORT,
240                               IOMUX_SD1_DATA1_PIN, IOMUX_SD1_DATA1_SEL,
241                               IOMUX_SD1_DATA1_DIR);
242     configure_gpio(IOMUX_SD1_DATA2_PORT,
243                               IOMUX_SD1_DATA2_PIN, IOMUX_SD1_DATA2_SEL,
244                               IOMUX_SD1_DATA2_DIR);
245     configure_gpio(IOMUX_SD1_DATA3_PORT,
246                               IOMUX_SD1_DATA3_PIN, IOMUX_SD1_DATA3_SEL,
247                               IOMUX_SD1_DATA3_DIR);
248
249     configure_gpio(IOMUX_SD2_DATA0_PORT,
250                               IOMUX_SD2_DATA0_PIN, IOMUX_SD2_DATA0_SEL,
251                               IOMUX_SD2_DATA0_DIR);
252     configure_gpio(IOMUX_SD2_DATA1_PORT,
253                               IOMUX_SD2_DATA1_PIN, IOMUX_SD2_DATA1_SEL,
254                               IOMUX_SD2_DATA1_DIR);
255     configure_gpio(IOMUX_SD2_DATA2_PORT,
256                              IOMUX_SD2_DATA2_PIN, IOMUX_SD2_DATA2_SEL,
257                              IOMUX_SD2_DATA2_DIR);
258     configure_gpio(IOMUX_SD2_DATA3_PORT,
259                               IOMUX_SD2_DATA3_PIN, IOMUX_SD2_DATA3_SEL,
260                               IOMUX_SD2_DATA3_DIR);
261
262     if((system_rev & 0xf) == 0x1) {
263         /* for Marley TO1.1.1, WP is not supported because of IC bug */
264         /* use default value */
265         configure_gpio(IOMUX_PAD_GPIO1_4_PORT,
266                                   IOMUX_PAD_GPIO1_4_PIN,
267                                   IOMUX_PAD_GPIO1_4_SEL_1,
268                                   IOMUX_PAD_GPIO1_4_DIR);
269     } else {   /* for TO 1.0 */
270         configure_gpio(IOMUX_PAD_GPIO1_4_PORT,
271                                   IOMUX_PAD_GPIO1_4_PIN,
272                                   IOMUX_PAD_GPIO1_4_SEL,
273                                   IOMUX_PAD_GPIO1_4_DIR);
274     }
275
276     configure_gpio(IOMUX_PAD_GPIO1_5_PORT,
277                               IOMUX_PAD_GPIO1_5_PIN,
278                               IOMUX_PAD_GPIO1_5_SEL,
279                               IOMUX_PAD_GPIO1_5_DIR);
280     configure_gpio(IOMUX_PAD_GPIO1_6_PORT,
281                               IOMUX_PAD_GPIO1_6_PIN,
282                               IOMUX_PAD_GPIO1_6_SEL,
283                               IOMUX_PAD_GPIO1_6_DIR);
284
285      /* Configure PAD setting for MMC/SD */
286      configure_pad(1, 65, 0x0190);
287      configure_pad(1, 66, 0x00d0);
288      configure_pad(1, 67, 0x01d0);
289      configure_pad(1, 68, 0x01d0);
290      configure_pad(1, 69, 0x01d0);
291      configure_pad(1, 70, 0x01A0);
292      configure_pad(1, 73, 0x0190);
293      configure_pad(1, 74, 0x0190);
294      configure_pad(1, 75, 0x0190);
295      configure_pad(1, 76, 0x0190);
296      configure_pad(1, 146, 0x01e0);
297      configure_pad(1, 147, 0x01e0);
298      configure_pad(1, 148, 0x0005);
299 }
300
301 #include CYGHWR_MEMORY_LAYOUT_H
302
303 typedef void code_fun(void);
304
305 void board_program_new_stack(void *func)
306 {
307     register CYG_ADDRESS stack_ptr asm("sp");
308     register CYG_ADDRESS old_stack asm("r4");
309     register code_fun *new_func asm("r0");
310     old_stack = stack_ptr;
311     stack_ptr = CYGMEM_REGION_ram + CYGMEM_REGION_ram_SIZE - sizeof(CYG_ADDRESS);
312     new_func = (code_fun*)func;
313     new_func();
314     stack_ptr = old_stack;
315 }
316
317 static void mx37_3stack_read_pmic_id()
318 {
319     struct mxc_i2c_request rq;
320     unsigned char buf[4];
321
322     if (i2c_init(I2C2_BASE_ADDR, 170000) == 0) {
323         rq.dev_addr = 0x8;
324         rq.reg_addr = 0x7;
325         rq.reg_addr_sz = 1;
326         rq.buffer_sz = 3;
327         rq.buffer = buf;
328         i2c_xfer(1, &rq, 1);
329         if ((buf[1] == 0x41) && (buf[2] == 0xc8 || buf[2] == 0xc9)) {
330             diag_printf("PMIC is Atlas AP Lite\n");
331             system_rev |= 0x1 << PMIC_ID_OFFSET;
332         } else {
333             /* Reinitialize I2C */
334             i2c_init(I2C2_BASE_ADDR, 170000);
335             rq.dev_addr = (0x34 >> 1);
336             rq.reg_addr = 0x0;
337             rq.reg_addr_sz = 1;
338             rq.buffer_sz = 2;
339             rq.buffer = buf;
340             i2c_xfer(1, &rq, 1);
341             if ((buf[0] == 0x61) && (buf[1] == 0x43)) {
342                 diag_printf("PMIC is WM8350\n");
343             } else {
344                 diag_printf("Unable to read the PMIC ID, assuming Atlas AP Lite\n");
345                 system_rev |= 0x1 << PMIC_ID_OFFSET;
346             }
347         }
348     } else {
349         diag_printf("Error Initializing I2C2, assuming PMIC to be Atlas AP Lite\n");
350         system_rev |= 0x1 << PMIC_ID_OFFSET;
351     }
352
353 }
354
355 RedBoot_init(mx37_3stack_read_pmic_id, RedBoot_INIT_PRIO(900));