1 //==========================================================================
5 // HAL misc board support code for the board
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.
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.
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
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.
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.
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.
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 //========================================================================*/
42 #include <pkgconf/hal.h>
43 #include <pkgconf/system.h>
45 #include CYGBLD_HAL_PLATFORM_H
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
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
61 // All the MM table layout is here:
62 #include <cyg/hal/hal_mm.h>
64 externC void* memset(void *, int, size_t);
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;
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)
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
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)
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
99 void hal_mmu_init(void)
101 unsigned long ttb_base = RAM_BANK0_BASE + 0x4000;
105 * Set the TTB register
107 asm volatile ("mcr p15,0,%0,c2,c0,0" : : "r"(ttb_base) /*:*/);
110 * Set the Domain Access Control Register
112 i = ARM_ACCESS_DACR_DEFAULT;
113 asm volatile ("mcr p15,0,%0,c3,c0,0" : : "r"(i) /*:*/);
116 * First clear all TT entries - ie Set them to Faulting
118 memset((void *)ttb_base, 0, ARM_FIRST_LEVEL_PAGE_TABLE_SIZE);
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 */
133 // Platform specific initialization
136 void plf_hardware_init(void)
140 v = 0x0040174A; // modified
141 writel(v, NFC_FLASH_CONFIG2_REG);
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);
148 v = NFC_WR_PROT_CS0 | NFC_WR_PROT_BLS_UNLOCK | NFC_WR_PROT_WPC;
149 writel(v, NFC_WR_PROT_REG);
151 writel(0, NFC_IPC_REG);
155 //Enable UART transceivers also reset the Ethernet/external UART
156 temp = readw(PBC_BASE + PBC_BCTRL1);
158 writew(0x8023, PBC_BASE + PBC_BCTRL1);
160 for (i = 0; i < 100000; i++) {
163 // clear the reset, toggle the LEDs
164 writew(0xDF, PBC_BASE + PBC_BCTRL1_CLR);
166 for (i = 0; i < 100000; i++) {
169 dummy = readb(0xB4000008);
170 dummy = readb(0xB4000007);
171 dummy = readb(0xB4000008);
172 dummy = readb(0xB4000007);
176 /* Reset interrupt status reg */
177 writew(0x1F, PBC_INT_REST);
178 writew(0x00, PBC_INT_REST);
179 writew(0xFFFF, PBC_INT_MASK);
183 writel(0x0, IOMUXC_BASE_ADDR + 0x15C);
184 writel(0x4, IOMUXC_BASE_ADDR + 0x604);
185 writel(0x1C5, IOMUXC_BASE_ADDR + 0x3BC);
188 writel(0x0, IOMUXC_BASE_ADDR + 0x160);
189 writel(0x1C5, IOMUXC_BASE_ADDR + 0x3C0);
192 writel(0x0, IOMUXC_BASE_ADDR + 0x164);
193 writel(0x4, IOMUXC_BASE_ADDR + 0x600);
194 writel(0x1C4, IOMUXC_BASE_ADDR + 0x3C4);
197 writel(0x0, IOMUXC_BASE_ADDR + 0x168);
198 writel(0x1C4, IOMUXC_BASE_ADDR + 0x3C8);
201 static void configure_gpio(cyg_uint32 port, cyg_uint32 pin,
202 cyg_uint32 io_select, cyg_uint32 dir)
204 cyg_uint32 tmp, rnum, roffset, cfg_val;
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;
215 if ((io_select & 0x100) == 0x100) {
216 /* Configure the direction of GPIO */
218 *data_dir_reg_ptr_array[port] |= (1 << pin);
220 *data_dir_reg_ptr_array[port] &= ~(1 << pin);
225 static void configure_pad(cyg_uint32 port, cyg_uint32 reg_index, cyg_uint32 val)
227 iomux_sw_mux_ctrl_reg_array[port][reg_index] = val;
230 void mxc_mmc_init(base_address)
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);
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);
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);
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);
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);
301 #include CYGHWR_MEMORY_LAYOUT_H
303 typedef void code_fun(void);
305 void board_program_new_stack(void *func)
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;
314 stack_ptr = old_stack;
317 static void mx37_3stack_read_pmic_id()
319 struct mxc_i2c_request rq;
320 unsigned char buf[4];
322 if (i2c_init(I2C2_BASE_ADDR, 170000) == 0) {
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;
333 /* Reinitialize I2C */
334 i2c_init(I2C2_BASE_ADDR, 170000);
335 rq.dev_addr = (0x34 >> 1);
341 if ((buf[0] == 0x61) && (buf[1] == 0x43)) {
342 diag_printf("PMIC is WM8350\n");
344 diag_printf("Unable to read the PMIC ID, assuming Atlas AP Lite\n");
345 system_rev |= 0x1 << PMIC_ID_OFFSET;
349 diag_printf("Error Initializing I2C2, assuming PMIC to be Atlas AP Lite\n");
350 system_rev |= 0x1 << PMIC_ID_OFFSET;
355 RedBoot_init(mx37_3stack_read_pmic_id, RedBoot_INIT_PRIO(900));