1 /* $NetBSD: netwalker_machdep.c,v 1.3 2010/12/09 05:00:14 bsh Exp $ */ 2 3 /* 4 * Copyright (c) 2002, 2003, 2005, 2010 Genetec Corporation. 5 * All rights reserved. 6 * Written by Hiroyuki Bessho for Genetec Corporation. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GENETEC CORPORATION 21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 * POSSIBILITY OF SUCH DAMAGE. 28 * 29 * Machine dependant functions for kernel setup for Sharp Netwalker. 30 * Based on iq80310_machhdep.c 31 */ 32 /* 33 * Copyright (c) 2001 Wasabi Systems, Inc. 34 * All rights reserved. 35 * 36 * Written by Jason R. Thorpe for Wasabi Systems, Inc. 37 * 38 * Redistribution and use in source and binary forms, with or without 39 * modification, are permitted provided that the following conditions 40 * are met: 41 * 1. Redistributions of source code must retain the above copyright 42 * notice, this list of conditions and the following disclaimer. 43 * 2. Redistributions in binary form must reproduce the above copyright 44 * notice, this list of conditions and the following disclaimer in the 45 * documentation and/or other materials provided with the distribution. 46 * 3. All advertising materials mentioning features or use of this software 47 * must display the following acknowledgement: 48 * This product includes software developed for the NetBSD Project by 49 * Wasabi Systems, Inc. 50 * 4. The name of Wasabi Systems, Inc. may not be used to endorse 51 * or promote products derived from this software without specific prior 52 * written permission. 53 * 54 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 55 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 56 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 57 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 58 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 59 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 60 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 61 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 62 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 63 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 64 * POSSIBILITY OF SUCH DAMAGE. 65 */ 66 67 /* 68 * Copyright (c) 1997,1998 Mark Brinicombe. 69 * Copyright (c) 1997,1998 Causality Limited. 70 * All rights reserved. 71 * 72 * Redistribution and use in source and binary forms, with or without 73 * modification, are permitted provided that the following conditions 74 * are met: 75 * 1. Redistributions of source code must retain the above copyright 76 * notice, this list of conditions and the following disclaimer. 77 * 2. Redistributions in binary form must reproduce the above copyright 78 * notice, this list of conditions and the following disclaimer in the 79 * documentation and/or other materials provided with the distribution. 80 * 3. All advertising materials mentioning features or use of this software 81 * must display the following acknowledgement: 82 * This product includes software developed by Mark Brinicombe 83 * for the NetBSD Project. 84 * 4. The name of the company nor the name of the author may be used to 85 * endorse or promote products derived from this software without specific 86 * prior written permission. 87 * 88 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 89 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 90 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 91 * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 92 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 93 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 94 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 95 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 96 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 97 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 98 * SUCH DAMAGE. 99 * 100 * Machine dependant functions for kernel setup for Intel IQ80310 evaluation 101 * boards using RedBoot firmware. 102 */ 103 104 #include <sys/cdefs.h> 105 __KERNEL_RCSID(0, "$NetBSD: netwalker_machdep.c,v 1.3 2010/12/09 05:00:14 bsh Exp $"); 106 107 #include "opt_ddb.h" 108 #include "opt_kgdb.h" 109 #include "opt_ipkdb.h" 110 #include "opt_pmap_debug.h" 111 #include "opt_md.h" 112 #include "opt_com.h" 113 #include "imxuart.h" 114 #include "opt_imxuart.h" 115 #include "opt_imx.h" 116 117 #include <sys/param.h> 118 #include <sys/device.h> 119 #include <sys/systm.h> 120 #include <sys/kernel.h> 121 #include <sys/exec.h> 122 #include <sys/proc.h> 123 #include <sys/msgbuf.h> 124 #include <sys/reboot.h> 125 #include <sys/termios.h> 126 #include <sys/ksyms.h> 127 128 #include <uvm/uvm_extern.h> 129 130 #include <sys/conf.h> 131 #include <dev/cons.h> 132 #include <dev/md.h> 133 134 #include <machine/db_machdep.h> 135 #include <ddb/db_sym.h> 136 #include <ddb/db_extern.h> 137 #ifdef KGDB 138 #include <sys/kgdb.h> 139 #endif 140 141 #include <machine/bootconfig.h> 142 #include <machine/bus.h> 143 #include <machine/cpu.h> 144 #include <machine/frame.h> 145 #include <arm/undefined.h> 146 147 #include <arm/arm32/pte.h> 148 #include <arm/arm32/machdep.h> 149 150 #include <arm/imx/imx51reg.h> 151 #include <arm/imx/imx51var.h> 152 #include <arm/imx/imxgpioreg.h> 153 #include <arm/imx/imxwdogreg.h> 154 #include <arm/imx/imxuartreg.h> 155 #include <arm/imx/imxuartvar.h> 156 #include <arm/imx/imx51_iomuxreg.h> 157 #include <evbarm/netwalker/netwalker_reg.h> 158 159 /* Kernel text starts 1MB in from the bottom of the kernel address space. */ 160 #define KERNEL_TEXT_BASE (KERNEL_BASE + 0x00100000) 161 #define KERNEL_VM_BASE (KERNEL_BASE + 0x01000000) 162 163 /* 164 * The range 0xc1000000 - 0xccffffff is available for kernel VM space 165 * Core-logic registers and I/O mappings occupy 0xfd000000 - 0xffffffff 166 */ 167 #define KERNEL_VM_SIZE 0x0C000000 168 169 170 /* 171 * Address to call from cpu_reset() to reset the machine. 172 * This is machine architecture dependant as it varies depending 173 * on where the ROM appears when you turn the MMU off. 174 */ 175 176 u_int cpu_reset_address = 0; 177 178 /* Define various stack sizes in pages */ 179 #define FIQ_STACK_SIZE 1 180 #define IRQ_STACK_SIZE 1 181 #define ABT_STACK_SIZE 1 182 #ifdef IPKDB 183 #define UND_STACK_SIZE 2 184 #else 185 #define UND_STACK_SIZE 1 186 #endif 187 188 BootConfig bootconfig; /* Boot config storage */ 189 char *boot_args = NULL; 190 char *boot_file = NULL; 191 192 vm_offset_t physical_start; 193 vm_offset_t physical_freestart; 194 vm_offset_t physical_freeend; 195 vm_offset_t physical_end; 196 u_int free_pages; 197 vm_offset_t pagetables_start; 198 199 /*int debug_flags;*/ 200 #ifndef PMAP_STATIC_L1S 201 int max_processes = 64; /* Default number */ 202 #endif /* !PMAP_STATIC_L1S */ 203 204 /* Physical and virtual addresses for some global pages */ 205 pv_addr_t fiqstack; 206 pv_addr_t irqstack; 207 pv_addr_t undstack; 208 pv_addr_t abtstack; 209 pv_addr_t kernelstack; 210 211 vm_offset_t msgbufphys; 212 213 extern u_int data_abort_handler_address; 214 extern u_int prefetch_abort_handler_address; 215 extern u_int undefined_handler_address; 216 extern char KERNEL_BASE_phys[]; 217 extern char KERNEL_BASE_virt[]; 218 extern char etext[], __data_start[], _edata[], __bss_start[], __bss_end__[]; 219 extern char _end[]; 220 extern int cpu_do_powersave; 221 222 #define KERNEL_PT_SYS 0 /* Page table for mapping proc0 zero page */ 223 #define KERNEL_PT_KERNEL 1 /* Page table for mapping kernel */ 224 #define KERNEL_PT_KERNEL_NUM 4 225 #define KERNEL_PT_VMDATA (KERNEL_PT_KERNEL+KERNEL_PT_KERNEL_NUM) 226 /* Page tables for mapping kernel VM */ 227 #define KERNEL_PT_VMDATA_NUM 4 /* start with 16MB of KVM */ 228 #define NUM_KERNEL_PTS (KERNEL_PT_VMDATA + KERNEL_PT_VMDATA_NUM) 229 230 pv_addr_t kernel_pt_table[NUM_KERNEL_PTS]; 231 232 /* 233 * Macros to translate between physical and virtual for a subset of the 234 * kernel address space. *Not* for general use. 235 */ 236 #define KERNEL_BASE_PHYS ((paddr_t)&KERNEL_BASE_phys) 237 #define KERNEL_BASE_VIRT ((vaddr_t)&KERNEL_BASE_virt) 238 #define KERN_VTOPHYS(va) \ 239 ((paddr_t)((vaddr_t)va - KERNEL_BASE_VIRT + KERNEL_BASE_PHYS)) 240 #define KERN_PHYSTOV(pa) \ 241 ((vaddr_t)((paddr_t)pa - KERNEL_BASE_PHYS + KERNEL_BASE_VIRT)) 242 243 244 /* Prototypes */ 245 246 void consinit(void); 247 #if 0 248 void process_kernel_args(char *); 249 #endif 250 251 #ifdef KGDB 252 void kgdb_port_init(void); 253 #endif 254 void change_clock(uint32_t v); 255 256 static void init_clocks(void); 257 static void setup_ioports(void); 258 #ifdef DEBUG_IOPORTS 259 void dump_registers(void); 260 #endif 261 262 bs_protos(bs_notimpl); 263 264 #ifndef CONSPEED 265 #define CONSPEED B115200 /* What RedBoot uses */ 266 #endif 267 #ifndef CONMODE 268 #define CONMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) /* 8N1 */ 269 #endif 270 271 int comcnspeed = CONSPEED; 272 int comcnmode = CONMODE; 273 274 /* 275 * void cpu_reboot(int howto, char *bootstr) 276 * 277 * Reboots the system 278 * 279 * Deal with any syncing, unmounting, dumping and shutdown hooks, 280 * then reset the CPU. 281 */ 282 void 283 cpu_reboot(int howto, char *bootstr) 284 { 285 #ifdef DIAGNOSTIC 286 /* info */ 287 printf("boot: howto=%08x curproc=%p\n", howto, curproc); 288 #endif 289 290 /* 291 * If we are still cold then hit the air brakes 292 * and crash to earth fast 293 */ 294 if (cold) { 295 doshutdownhooks(); 296 pmf_system_shutdown(boothowto); 297 printf("The operating system has halted.\n"); 298 printf("Please press any key to reboot.\n\n"); 299 cngetc(); 300 printf("rebooting...\n"); 301 cpu_reset(); 302 /*NOTREACHED*/ 303 } 304 305 /* Disable console buffering */ 306 /* cnpollc(1);*/ 307 308 /* 309 * If RB_NOSYNC was not specified sync the discs. 310 * Note: Unless cold is set to 1 here, syslogd will die during the 311 * unmount. It looks like syslogd is getting woken up only to find 312 * that it cannot page part of the binary in as the filesystem has 313 * been unmounted. 314 */ 315 if (!(howto & RB_NOSYNC)) 316 bootsync(); 317 318 /* Say NO to interrupts */ 319 splhigh(); 320 321 /* Do a dump if requested. */ 322 if ((howto & (RB_DUMP | RB_HALT)) == RB_DUMP) 323 dumpsys(); 324 325 /* Run any shutdown hooks */ 326 doshutdownhooks(); 327 328 pmf_system_shutdown(boothowto); 329 330 /* Make sure IRQ's are disabled */ 331 IRQdisable; 332 333 if (howto & RB_HALT) { 334 printf("The operating system has halted.\n"); 335 printf("Please press any key to reboot.\n\n"); 336 cngetc(); 337 } 338 339 printf("rebooting...\n"); 340 cpu_reset(); 341 /*NOTREACHED*/ 342 } 343 344 /* 345 * Static device mappings. These peripheral registers are mapped at 346 * fixed virtual addresses very early in netwalker_start() so that we 347 * can use them while booting the kernel, and stay at the same address 348 * throughout whole kernel's life time. 349 * 350 * We use this table twice; once with bootstrap page table, and once 351 * with kernel's page table which we build up in initarm(). 352 */ 353 354 #define _A(a) ((a) & ~L1_S_OFFSET) 355 #define _S(s) (((s) + L1_S_SIZE - 1) & ~(L1_S_SIZE-1)) 356 357 static const struct pmap_devmap netwalker_devmap[] = { 358 { 359 /* for UART1, IOMUXC */ 360 NETWALKER_IO_VBASE0, 361 _A(NETWALKER_IO_PBASE0), 362 L1_S_SIZE * 4, 363 VM_PROT_READ|VM_PROT_WRITE, PTE_NOCACHE 364 }, 365 {0, 0, 0, 0, 0 } 366 }; 367 368 #ifndef MEMSTART 369 #define MEMSTART 0x90000000 370 #endif 371 #ifndef MEMSIZE 372 #define MEMSIZE 512 373 #endif 374 375 /* 376 * u_int initarm(...) 377 * 378 * Initial entry point on startup. This gets called before main() is 379 * entered. 380 * It should be responsible for setting up everything that must be 381 * in place when main is called. 382 * This includes 383 * Taking a copy of the boot configuration structure. 384 * Initialising the physical console so characters can be printed. 385 * Setting up page tables for the kernel 386 * Relocating the kernel to the bottom of physical memory 387 */ 388 u_int 389 initarm(void *arg) 390 { 391 int loop; 392 int loop1; 393 vaddr_t l1pagetable; 394 395 #ifdef RBFLAGS 396 boothowto |= RBFLAGS; 397 #endif 398 399 disable_interrupts(I32_bit|F32_bit); 400 /* XXX move to netwalker_start.S */ 401 402 /* Register devmap for devices we mapped in start */ 403 pmap_devmap_register(netwalker_devmap); 404 405 setup_ioports(); 406 407 consinit(); 408 409 #ifdef DEBUG_IOPORTS 410 dump_registers(); 411 #endif 412 413 /* 414 * Heads up ... Setup the CPU / MMU / TLB functions 415 */ 416 if (set_cpufuncs()) 417 panic("cpu not recognized!"); 418 419 #ifdef NO_POWERSAVE 420 cpu_do_powersave=0; 421 #endif 422 423 init_clocks(); 424 425 #ifdef KGDB 426 kgdb_port_init(); 427 #endif 428 429 /* Talk to the user */ 430 printf("\nNetBSD/evbarm (netwalker) booting ...\n"); 431 432 /* 433 * Ok we have the following memory map 434 * 435 * Physical Address Range Description 436 * ----------------------- ---------------------------------- 437 * 438 * 0x90000000 - 0x97FFFFFF DDR SDRAM (128MByte) 439 * 440 * The initarm() has the responsibility for creating the kernel 441 * page tables. 442 * It must also set up various memory pointers that are used 443 * by pmap etc. 444 */ 445 446 #if 0 447 /* 448 * Examine the boot args string for options we need to know about 449 * now. 450 */ 451 process_kernel_args((char *)nwbootinfo.bt_args); 452 #endif 453 454 #ifdef VERBOSE_INIT_ARM 455 printf("initarm: Configuring system ...\n"); 456 #endif 457 /* Fake bootconfig structure for the benefit of pmap.c */ 458 /* XXX must make the memory description h/w independent */ 459 bootconfig.dramblocks = 1; 460 bootconfig.dram[0].address = MEMSTART; 461 bootconfig.dram[0].pages = (MEMSIZE * 1024 * 1024)/ PAGE_SIZE; 462 463 /* 464 * Set up the variables that define the availablilty of 465 * physical memory. For now, we're going to set 466 * physical_freestart to 0x80100000 (where the kernel 467 * was loaded), and allocate the memory we need downwards. 468 * If we get too close to the bottom of SDRAM, we 469 * will panic. We will update physical_freestart and 470 * physical_freeend later to reflect what pmap_bootstrap() 471 * wants to see. 472 * 473 * XXX pmap_bootstrap() needs an enema. 474 */ 475 physical_start = bootconfig.dram[0].address; 476 physical_end = physical_start + (bootconfig.dram[0].pages * PAGE_SIZE); 477 478 physical_freestart = 0x90000000UL; /* top of loadaddres */ 479 physical_freeend = 0x90100000UL; /* base of kernel */ 480 481 physmem = (physical_end - physical_start) / PAGE_SIZE; 482 483 #ifdef VERBOSE_INIT_ARM 484 /* Tell the user about the memory */ 485 printf("physmemory: %d pages at 0x%08lx -> 0x%08lx\n", physmem, 486 physical_start, physical_end - 1); 487 #endif 488 489 /* 490 * Okay, the kernel starts 1MB in from the bottom of physical 491 * memory. We are going to allocate our bootstrap pages downwards 492 * from there. 493 * 494 * We need to allocate some fixed page tables to get the kernel 495 * going. We allocate one page directory and a number of page 496 * tables and store the physical addresses in the kernel_pt_table 497 * array. 498 * 499 * The kernel page directory must be on a 16K boundary. The page 500 * tables must be on 4K boundaries. What we do is allocate the 501 * page directory on the first 16K boundary that we encounter, and 502 * the page tables on 4K boundaries otherwise. Since we allocate 503 * at least 3 L2 page tables, we are guaranteed to encounter at 504 * least one 16K aligned region. 505 */ 506 507 #ifdef VERBOSE_INIT_ARM 508 printf("Allocating page tables\n"); 509 #endif 510 511 free_pages = (physical_freeend - physical_freestart) / PAGE_SIZE; 512 513 #ifdef VERBOSE_INIT_ARM 514 printf("freestart = 0x%08lx, free_pages = %d (0x%08x)\n", 515 physical_freestart, free_pages, free_pages); 516 #endif 517 518 /* Define a macro to simplify memory allocation */ 519 #define valloc_pages(var, np) \ 520 alloc_pages((var).pv_pa, (np)); \ 521 (var).pv_va = KERNEL_BASE + (var).pv_pa - physical_start; 522 523 #define alloc_pages(var, np) \ 524 physical_freeend -= ((np) * PAGE_SIZE); \ 525 if (physical_freeend < physical_freestart) \ 526 panic("initarm: out of memory"); \ 527 (var) = physical_freeend; \ 528 free_pages -= (np); \ 529 memset((char *)(var), 0, ((np) * PAGE_SIZE)); 530 531 loop1 = 0; 532 for (loop = 0; loop <= NUM_KERNEL_PTS; ++loop) { 533 /* Are we 16KB aligned for an L1 ? */ 534 if (((physical_freeend - L1_TABLE_SIZE) & (L1_TABLE_SIZE - 1)) == 0 535 && kernel_l1pt.pv_pa == 0) { 536 valloc_pages(kernel_l1pt, L1_TABLE_SIZE / PAGE_SIZE); 537 } else { 538 valloc_pages(kernel_pt_table[loop1], 539 L2_TABLE_SIZE / PAGE_SIZE); 540 ++loop1; 541 } 542 } 543 544 /* This should never be able to happen but better confirm that. */ 545 if (!kernel_l1pt.pv_pa || (kernel_l1pt.pv_pa & (L1_TABLE_SIZE-1)) != 0) 546 panic("initarm: Failed to align the kernel page directory"); 547 548 /* 549 * Allocate a page for the system page mapped to V0x00000000 550 * This page will just contain the system vectors and can be 551 * shared by all processes. 552 */ 553 valloc_pages(systempage, 1); 554 systempage.pv_va = ARM_VECTORS_HIGH; 555 556 /* Allocate stacks for all modes */ 557 valloc_pages(fiqstack, FIQ_STACK_SIZE); 558 valloc_pages(irqstack, IRQ_STACK_SIZE); 559 valloc_pages(abtstack, ABT_STACK_SIZE); 560 valloc_pages(undstack, UND_STACK_SIZE); 561 valloc_pages(kernelstack, UPAGES); 562 563 #ifdef VERBOSE_INIT_ARM 564 printf("FIQ stack: p0x%08lx v0x%08lx\n", fiqstack.pv_pa, 565 fiqstack.pv_va); 566 printf("IRQ stack: p0x%08lx v0x%08lx\n", irqstack.pv_pa, 567 irqstack.pv_va); 568 printf("ABT stack: p0x%08lx v0x%08lx\n", abtstack.pv_pa, 569 abtstack.pv_va); 570 printf("UND stack: p0x%08lx v0x%08lx\n", undstack.pv_pa, 571 undstack.pv_va); 572 printf("SVC stack: p0x%08lx v0x%08lx\n", kernelstack.pv_pa, 573 kernelstack.pv_va); 574 #endif 575 576 alloc_pages(msgbufphys, round_page(MSGBUFSIZE) / PAGE_SIZE); 577 578 /* 579 * Ok we have allocated physical pages for the primary kernel 580 * page tables 581 */ 582 583 #ifdef VERBOSE_INIT_ARM 584 printf("Creating L1 page table at p0x%08lx v0x%08lx\n", 585 kernel_l1pt.pv_pa, kernel_l1pt.pv_va); 586 #endif 587 588 /* 589 * Now we start construction of the L1 page table 590 * We start by mapping the L2 page tables into the L1. 591 * This means that we can replace L1 mappings later on if necessary 592 */ 593 l1pagetable = kernel_l1pt.pv_pa; 594 595 /* Map the L2 pages tables in the L1 page table */ 596 pmap_link_l2pt(l1pagetable, ARM_VECTORS_HIGH & ~(0x00400000 - 1), 597 &kernel_pt_table[KERNEL_PT_SYS]); 598 for (loop = 0; loop < KERNEL_PT_KERNEL_NUM; loop++) 599 pmap_link_l2pt(l1pagetable, KERNEL_BASE + loop * 0x00400000, 600 &kernel_pt_table[KERNEL_PT_KERNEL + loop]); 601 for (loop = 0; loop < KERNEL_PT_VMDATA_NUM; loop++) 602 pmap_link_l2pt(l1pagetable, KERNEL_VM_BASE + loop * 0x00400000, 603 &kernel_pt_table[KERNEL_PT_VMDATA + loop]); 604 605 /* update the top of the kernel VM */ 606 pmap_curmaxkvaddr = 607 KERNEL_VM_BASE + (KERNEL_PT_VMDATA_NUM * 0x00400000); 608 609 #ifdef VERBOSE_INIT_ARM 610 printf("Mapping kernel\n"); 611 #endif 612 613 /* Now we fill in the L2 pagetable for the kernel static code/data */ 614 #define round_L_page(x) (((x) + L2_L_OFFSET) & L2_L_FRAME) 615 { 616 size_t textsize = round_L_page((size_t)etext - KERNEL_TEXT_BASE); 617 size_t totalsize = round_L_page((size_t)_end - KERNEL_TEXT_BASE); 618 u_int logical; 619 620 621 #ifdef VERBOSE_INIT_ARM 622 printf("%s: etext %lx, _end %lx\n", 623 __func__, (uintptr_t)etext, (uintptr_t)_end); 624 printf("%s: textsize %#lx, totalsize %#lx\n", 625 __func__, textsize, totalsize); 626 #endif 627 logical = 0x00100000; /* offset of kernel in RAM */ 628 629 /* Map text section read-only. */ 630 logical += pmap_map_chunk(l1pagetable, KERNEL_BASE + logical, 631 physical_start + logical, textsize, 632 VM_PROT_READ|VM_PROT_EXECUTE, PTE_CACHE); 633 634 /* Map data and bss sections read-write. */ 635 logical += pmap_map_chunk(l1pagetable, KERNEL_BASE + logical, 636 physical_start + logical, totalsize - textsize, 637 VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); 638 } 639 640 #ifdef VERBOSE_INIT_ARM 641 printf("Constructing L2 page tables\n"); 642 #endif 643 644 /* Map the stack pages */ 645 pmap_map_chunk(l1pagetable, fiqstack.pv_va, fiqstack.pv_pa, 646 FIQ_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); 647 pmap_map_chunk(l1pagetable, irqstack.pv_va, irqstack.pv_pa, 648 IRQ_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); 649 pmap_map_chunk(l1pagetable, abtstack.pv_va, abtstack.pv_pa, 650 ABT_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); 651 pmap_map_chunk(l1pagetable, undstack.pv_va, undstack.pv_pa, 652 UND_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); 653 pmap_map_chunk(l1pagetable, kernelstack.pv_va, kernelstack.pv_pa, 654 UPAGES * PAGE_SIZE, VM_PROT_READ | VM_PROT_WRITE, PTE_CACHE); 655 656 pmap_map_chunk(l1pagetable, kernel_l1pt.pv_va, kernel_l1pt.pv_pa, 657 L1_TABLE_SIZE, VM_PROT_READ | VM_PROT_WRITE, PTE_PAGETABLE); 658 659 for (loop = 0; loop < NUM_KERNEL_PTS; ++loop) { 660 pmap_map_chunk(l1pagetable, kernel_pt_table[loop].pv_va, 661 kernel_pt_table[loop].pv_pa, L2_TABLE_SIZE, 662 VM_PROT_READ|VM_PROT_WRITE, PTE_PAGETABLE); 663 } 664 665 /* Map the vector page. */ 666 #if 0 667 /* MULTI-ICE requires that page 0 is NC/NB so that it can download the 668 * cache-clean code there. */ 669 pmap_map_entry(l1pagetable, ARM_VECTORS_HIGH, systempage.pv_pa, 670 VM_PROT_READ|VM_PROT_WRITE, PTE_NOCACHE); 671 #else 672 pmap_map_entry(l1pagetable, ARM_VECTORS_HIGH, systempage.pv_pa, 673 VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); 674 #endif 675 676 /* 677 * map integrated peripherals at same address in l1pagetable 678 * so that we can continue to use console. 679 */ 680 pmap_devmap_bootstrap(l1pagetable, netwalker_devmap); 681 682 /* 683 * Now we have the real page tables in place so we can switch to them. 684 * Once this is done we will be running with the REAL kernel page 685 * tables. 686 */ 687 688 /* 689 * Update the physical_freestart/physical_freeend/free_pages 690 * variables. 691 */ 692 physical_freestart = physical_start + 693 (((((uintptr_t) _end) + PGOFSET) & ~PGOFSET) - KERNEL_BASE); 694 physical_freeend = physical_end; 695 free_pages = 696 (physical_freeend - physical_freestart) / PAGE_SIZE; 697 698 #ifdef VERBOSE_INIT_ARM 699 /* Tell the user about where all the bits and pieces live. */ 700 printf("%22s Physical Virtual Num\n", " "); 701 printf("%22s Starting Ending Starting Ending Pages\n", " "); 702 703 static const char mem_fmt[] = 704 "%20s: 0x%08lx 0x%08lx 0x%08lx 0x%08lx %d\n"; 705 static const char mem_fmt_nov[] = 706 "%20s: 0x%08lx 0x%08lx %d\n"; 707 708 printf(mem_fmt, "SDRAM", physical_start, physical_end-1, 709 KERN_PHYSTOV(physical_start), KERN_PHYSTOV(physical_end-1), 710 physmem); 711 printf(mem_fmt, "text section", 712 (paddr_t)KERNEL_BASE_phys, KERN_VTOPHYS(etext-1), 713 (vaddr_t)KERNEL_BASE_virt, (vaddr_t)etext-1, 714 (int)(round_L_page((size_t)etext - KERNEL_TEXT_BASE) / PAGE_SIZE)); 715 printf(mem_fmt, "data section", 716 KERN_VTOPHYS(__data_start), KERN_VTOPHYS(_edata), 717 (vaddr_t)__data_start, (vaddr_t)_edata, 718 (int)((round_page((vaddr_t)_edata) 719 - trunc_page((vaddr_t)__data_start)) / PAGE_SIZE)); 720 printf(mem_fmt, "bss section", 721 KERN_VTOPHYS(__bss_start), KERN_VTOPHYS(__bss_end__), 722 (vaddr_t)__bss_start, (vaddr_t)__bss_end__, 723 (int)((round_page((vaddr_t)__bss_end__) 724 - trunc_page((vaddr_t)__bss_start)) / PAGE_SIZE)); 725 printf(mem_fmt, "L1 page directory", 726 kernel_l1pt.pv_pa, kernel_l1pt.pv_pa + L1_TABLE_SIZE - 1, 727 kernel_l1pt.pv_va, kernel_l1pt.pv_va + L1_TABLE_SIZE - 1, 728 L1_TABLE_SIZE / PAGE_SIZE); 729 printf(mem_fmt, "Exception Vectors", 730 systempage.pv_pa, systempage.pv_pa + PAGE_SIZE - 1, 731 systempage.pv_va, systempage.pv_va + PAGE_SIZE - 1, 732 1); 733 printf(mem_fmt, "FIQ stack", 734 fiqstack.pv_pa, fiqstack.pv_pa + (FIQ_STACK_SIZE * PAGE_SIZE) - 1, 735 fiqstack.pv_va, fiqstack.pv_va + (FIQ_STACK_SIZE * PAGE_SIZE) - 1, 736 FIQ_STACK_SIZE); 737 printf(mem_fmt, "IRQ stack", 738 irqstack.pv_pa, irqstack.pv_pa + (IRQ_STACK_SIZE * PAGE_SIZE) - 1, 739 irqstack.pv_va, irqstack.pv_va + (IRQ_STACK_SIZE * PAGE_SIZE) - 1, 740 IRQ_STACK_SIZE); 741 printf(mem_fmt, "ABT stack", 742 abtstack.pv_pa, abtstack.pv_pa + (ABT_STACK_SIZE * PAGE_SIZE) - 1, 743 abtstack.pv_va, abtstack.pv_va + (ABT_STACK_SIZE * PAGE_SIZE) - 1, 744 ABT_STACK_SIZE); 745 printf(mem_fmt, "UND stack", 746 undstack.pv_pa, undstack.pv_pa + (UND_STACK_SIZE * PAGE_SIZE) - 1, 747 undstack.pv_va, undstack.pv_va + (UND_STACK_SIZE * PAGE_SIZE) - 1, 748 UND_STACK_SIZE); 749 printf(mem_fmt, "SVC stack", 750 kernelstack.pv_pa, kernelstack.pv_pa + (UPAGES * PAGE_SIZE) - 1, 751 kernelstack.pv_va, kernelstack.pv_va + (UPAGES * PAGE_SIZE) - 1, 752 UPAGES); 753 printf(mem_fmt_nov, "Message Buffer", 754 msgbufphys, msgbufphys + round_page(MSGBUFSIZE) - 1, round_page(MSGBUFSIZE) / PAGE_SIZE); 755 printf(mem_fmt, "Free Memory", physical_freestart, physical_freeend-1, 756 KERN_PHYSTOV(physical_freestart), KERN_PHYSTOV(physical_freeend-1), 757 free_pages); 758 #endif 759 760 /* Switch tables */ 761 #ifdef VERBOSE_INIT_ARM 762 printf("freestart = 0x%08lx, free_pages = %d (0x%x)\n", 763 physical_freestart, free_pages, free_pages); 764 printf("switching to new L1 page table @%#lx...", kernel_l1pt.pv_pa); 765 #endif 766 767 cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT); 768 cpu_setttb(kernel_l1pt.pv_pa); 769 cpu_tlb_flushID(); 770 cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)); 771 772 /* 773 * Moved from cpu_startup() as data_abort_handler() references 774 * this during uvm init 775 */ 776 uvm_lwp_setuarea(&lwp0, kernelstack.pv_va); 777 778 #ifdef VERBOSE_INIT_ARM 779 printf("bootstrap done.\n"); 780 #endif 781 782 arm32_vector_init(ARM_VECTORS_HIGH, ARM_VEC_ALL); 783 784 /* 785 * Pages were allocated during the secondary bootstrap for the 786 * stacks for different CPU modes. 787 * We must now set the r13 registers in the different CPU modes to 788 * point to these stacks. 789 * Since the ARM stacks use STMFD etc. we must set r13 to the top end 790 * of the stack memory. 791 */ 792 #ifdef VERBOSE_INIT_ARM 793 printf("init subsystems: stacks "); 794 #endif 795 set_stackptr(PSR_FIQ32_MODE, fiqstack.pv_va + FIQ_STACK_SIZE * PAGE_SIZE); 796 set_stackptr(PSR_IRQ32_MODE, irqstack.pv_va + IRQ_STACK_SIZE * PAGE_SIZE); 797 set_stackptr(PSR_ABT32_MODE, abtstack.pv_va + ABT_STACK_SIZE * PAGE_SIZE); 798 set_stackptr(PSR_UND32_MODE, undstack.pv_va + UND_STACK_SIZE * PAGE_SIZE); 799 800 /* 801 * Well we should set a data abort handler. 802 * Once things get going this will change as we will need a proper 803 * handler. 804 * Until then we will use a handler that just panics but tells us 805 * why. 806 * Initialisation of the vectors will just panic on a data abort. 807 * This just fills in a slightly better one. 808 */ 809 #ifdef VERBOSE_INIT_ARM 810 printf("vectors "); 811 #endif 812 data_abort_handler_address = (u_int)data_abort_handler; 813 prefetch_abort_handler_address = (u_int)prefetch_abort_handler; 814 undefined_handler_address = (u_int)undefinedinstruction_bounce; 815 816 /* Initialise the undefined instruction handlers */ 817 #ifdef VERBOSE_INIT_ARM 818 printf("undefined "); 819 #endif 820 undefined_init(); 821 822 /* Load memory into UVM. */ 823 #ifdef VERBOSE_INIT_ARM 824 printf("page "); 825 #endif 826 uvm_setpagesize(); /* initialize PAGE_SIZE-dependent variables */ 827 uvm_page_physload(atop(physical_freestart), atop(physical_freeend), 828 atop(physical_freestart), atop(physical_freeend), 829 VM_FREELIST_DEFAULT); 830 831 /* Boot strap pmap telling it where the kernel page table is */ 832 #ifdef VERBOSE_INIT_ARM 833 printf("pmap "); 834 #endif 835 pmap_bootstrap(KERNEL_VM_BASE, KERNEL_VM_BASE + KERNEL_VM_SIZE); 836 837 #ifdef __HAVE_MEMORY_DISK__ 838 md_root_setconf(memory_disk, sizeof memory_disk); 839 #endif 840 841 #ifdef VERBOSE_INIT_ARM 842 printf("done.\n"); 843 #endif 844 845 /* disable power down counter in watch dog, 846 This must be done within 16 seconds of start-up. */ 847 ioreg16_write(NETWALKER_WDOG_VBASE + IMX_WDOG_WMCR, 0); 848 849 #ifdef IPKDB 850 /* Initialise ipkdb */ 851 ipkdb_init(); 852 if (boothowto & RB_KDB) 853 ipkdb_connect(0); 854 #endif 855 856 #ifdef KGDB 857 if (boothowto & RB_KDB) { 858 kgdb_debug_init = 1; 859 kgdb_connect(1); 860 } 861 #endif 862 863 #ifdef DDB 864 #ifdef VERBOSE_INIT_ARM 865 printf("ddb "); 866 #endif 867 db_machine_init(); 868 869 /* Firmware doesn't load symbols. */ 870 ddb_init(0, NULL, NULL); 871 872 if (boothowto & RB_KDB) 873 Debugger(); 874 #endif 875 876 877 878 printf("initarm done.\n"); 879 880 /* We return the new stack pointer address */ 881 return(kernelstack.pv_va + USPACE_SVC_STACK_TOP); 882 } 883 884 #if 0 885 void 886 process_kernel_args(char *args) 887 { 888 889 boothowto = 0; 890 891 /* Make a local copy of the bootargs */ 892 strncpy(bootargs, args, MAX_BOOT_STRING); 893 894 args = bootargs; 895 boot_file = bootargs; 896 897 /* Skip the kernel image filename */ 898 while (*args != ' ' && *args != 0) 899 ++args; 900 901 if (*args != 0) 902 *args++ = 0; 903 904 while (*args == ' ') 905 ++args; 906 907 boot_args = args; 908 909 printf("bootfile: %s\n", boot_file); 910 printf("bootargs: %s\n", boot_args); 911 912 parse_mi_bootargs(boot_args); 913 } 914 #endif 915 916 static void 917 init_clocks(void) 918 { 919 extern void cortexa8_pmc_ccnt_init(void); 920 921 cortexa8_pmc_ccnt_init(); 922 } 923 924 struct iomux_setup { 925 size_t pad_ctl_reg; 926 uint32_t pad_ctl_val; 927 size_t mux_ctl_reg; 928 uint32_t mux_ctl_val; 929 }; 930 931 #define IOMUX_DATA(padname, mux, pad) \ 932 IOMUX_DATA2(__CONCAT(IOMUXC_SW_MUX_CTL_PAD_,padname), mux, \ 933 __CONCAT(IOMUXC_SW_PAD_CTL_PAD_,padname), pad) 934 935 936 #define IOMUX_DATA2(muxreg, muxval, padreg, padval) \ 937 { \ 938 .pad_ctl_reg = (padreg), \ 939 .pad_ctl_val = (padval), \ 940 .mux_ctl_reg = (muxreg), \ 941 .mux_ctl_val = (muxval) \ 942 } 943 944 945 const struct iomux_setup iomux_setup_data[] = { 946 947 /* left buttons */ 948 IOMUX_DATA(EIM_EB2, IOMUX_CONFIG_ALT1, 949 PAD_CTL_HYS), 950 /* right buttons */ 951 IOMUX_DATA(EIM_EB3, IOMUX_CONFIG_ALT1, 952 PAD_CTL_HYS), 953 954 /* UART1 */ 955 #if 1 956 IOMUX_DATA(UART1_RXD, IOMUX_CONFIG_ALT0, 957 PAD_CTL_DSE_HIGH | PAD_CTL_SRE), 958 #else 959 IOMUX_DATA(UART1_RXD, IOMUX_CONFIG_ALT3, /* gpio4[28] */ 960 PAD_CTL_DSE_HIGH | PAD_CTL_SRE), 961 #endif 962 IOMUX_DATA(UART1_TXD, IOMUX_CONFIG_ALT0, 963 PAD_CTL_DSE_HIGH | PAD_CTL_SRE), 964 IOMUX_DATA(UART1_RTS, IOMUX_CONFIG_ALT0, 965 PAD_CTL_DSE_HIGH), 966 IOMUX_DATA(UART1_CTS, IOMUX_CONFIG_ALT0, 967 PAD_CTL_DSE_HIGH), 968 }; 969 970 static void 971 setup_ioports(void) 972 { 973 int i; 974 const struct iomux_setup *p; 975 976 #if 0 /* These are all done already by Netwalker's bootloader. */ 977 /* set IO multiplexor for UART1 */ 978 uint32_t reg; 979 uint32_t addr; 980 981 /* input */ 982 addr = NETWALKER_IOMUXC_VBASE + MUX_IN_UART1_IPP_UART_RXD_MUX; 983 reg = INPUT_DAISY_0; 984 ioreg_write(addr, reg); 985 addr = NETWALKER_IOMUXC_VBASE + MUX_IN_UART1_IPP_UART_RTS_B; 986 reg = INPUT_DAISY_0; 987 ioreg_write(addr, reg); 988 #endif 989 990 for (i=0; i < __arraycount(iomux_setup_data); ++i) { 991 p = iomux_setup_data + i; 992 993 ioreg_write(NETWALKER_IOMUXC_VBASE + 994 p->pad_ctl_reg, 995 p->pad_ctl_val); 996 ioreg_write(NETWALKER_IOMUXC_VBASE + 997 p->mux_ctl_reg, 998 p->mux_ctl_val); 999 } 1000 1001 1002 #if 0 /* already done by bootloader */ 1003 /* GPIO2[22,23]: input (left/right button) 1004 GPIO2[21]: input (power button) */ 1005 ioreg_write(NETWALKER_GPIO_VBASE(2) + GPIO_DIR, 1006 ~__BITS(21,23) & 1007 ioreg_read(NETWALKER_GPIO_VBASE(2) + GPIO_DIR)); 1008 #endif 1009 1010 #if 0 /* already done by bootloader */ 1011 /* GPIO4[12]: input (cover switch) */ 1012 ioreg_write(NETWALKER_GPIO_VBASE(4) + GPIO_DIR, 1013 ~__BIT(12) & 1014 ioreg_read(NETWALKER_GPIO_VBASE(4) + GPIO_DIR)); 1015 #endif 1016 } 1017 1018 1019 #ifdef CONSDEVNAME 1020 const char consdevname[] = CONSDEVNAME; 1021 1022 #ifndef CONMODE 1023 #define CONMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) /* 8N1 */ 1024 #endif 1025 #ifndef CONSPEED 1026 #define CONSPEED 115200 1027 #endif 1028 1029 int consmode = CONMODE; 1030 int consrate = CONSPEED; 1031 1032 #endif /* CONSDEVNAME */ 1033 1034 #ifndef IMXUART_FREQ 1035 #define IMXUART_FREQ 66355200 1036 #endif 1037 1038 void 1039 consinit(void) 1040 { 1041 static int consinit_called = 0; 1042 1043 if (consinit_called) 1044 return; 1045 1046 consinit_called = 1; 1047 1048 #ifdef CONSDEVNAME 1049 1050 #if NIMXUART > 0 1051 imxuart_set_frequency(IMXUART_FREQ, 2); 1052 #endif 1053 1054 #if (NIMXUART > 0) && defined(IMXUARTCONSOLE) 1055 if (strcmp(consdevname, "imxuart") == 0) { 1056 paddr_t consaddr; 1057 #ifdef CONADDR 1058 consaddr = CONADDR; 1059 #else 1060 consaddr = IMX51_UART1_BASE; 1061 #endif 1062 imxuart_cons_attach(&imx_bs_tag, consaddr, consrate, consmode); 1063 return; 1064 } 1065 #endif 1066 1067 #endif 1068 1069 #if (NWSDISPLAY > 0) && defined(IMXLCDCONSOLE) 1070 { 1071 extern void netwalker_cnattach(void); 1072 netwalker_cnattach(); 1073 } 1074 #endif 1075 } 1076 1077 #ifdef KGDB 1078 #ifndef KGDB_DEVNAME 1079 #define KGDB_DEVNAME "imxuart" 1080 #endif 1081 #ifndef KGDB_DEVMODE 1082 #define KGDB_DEVMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) /* 8N1 */ 1083 #endif 1084 1085 const char kgdb_devname[20] = KGDB_DEVNAME; 1086 int kgdb_mode = KGDB_DEVMODE; 1087 int kgdb_addr = KGDB_DEVADDR; 1088 extern int kgdb_rate; /* defined in kgdb_stub.c */ 1089 1090 void 1091 kgdb_port_init(void) 1092 { 1093 #if (NIMXUART > 0) 1094 if (strcmp(kgdb_devname, "imxuart") == 0) { 1095 imxuart_kgdb_attach(&imx_bs_tag, kgdb_addr, 1096 kgdb_rate, kgdb_mode); 1097 return; 1098 } 1099 1100 #endif 1101 } 1102 #endif 1103 1104 1105 #ifdef DEBUG_IOPORTS 1106 static void dump_sub(paddr_t addr, size_t size) 1107 { 1108 paddr_t end = addr + size; 1109 1110 for (; addr < end; addr += 4) { 1111 if (addr % 16 == 0) 1112 printf("%08x: ", (u_int)addr); 1113 printf("%08x ", ioreg_read(addr)); 1114 1115 if (addr % 16 == 12) 1116 printf("\n"); 1117 } 1118 printf("\n"); 1119 } 1120 1121 void 1122 dump_registers(void) 1123 { 1124 paddr_t pa; 1125 int i; 1126 1127 dump_sub(IOMUXC_BASE, IOMUXC_USBOH3_IPP_IND_UH3_STP_SELECT_INPUT + 4); 1128 1129 for (i = 1; i <= 4; ++i) { 1130 dump_sub(GPIO_BASE(i), GPIO_SIZE); 1131 } 1132 1133 printf("\nwatchdog: "); 1134 for (pa = WDOG1_BASE; pa <= WDOG1_BASE + IMX_WDOG_WMCR; 1135 pa += 2) { 1136 printf("%04x ", *(volatile uint16_t *)pa); 1137 } 1138 printf("\n"); 1139 1140 printf("\nCCM\n"); 1141 dump_sub(CCM_BASE, CCM_SIZE); 1142 1143 #if 0 1144 /* disable power down counter in watch dog, 1145 This must be done within 16 seconds of start-up. */ 1146 ioreg16_write(NETWALKER_WDOG_VBASE + IMX_WDOG_WMCR, 0); 1147 1148 /* read left/right buttons */ 1149 for (;;) { 1150 uint32_t reg; 1151 1152 reg = ioreg_read(GPIO_BASE(2) + GPIO_DR); 1153 printf("\r%08x", reg); 1154 reg = ioreg_read(GPIO_BASE(4) + GPIO_DR); 1155 printf(" %08x", reg); 1156 1157 #if 0 1158 ioreg16_write(WDOG1_BASE + IMX_WDOG_WSR, WSR_MAGIC1); 1159 ioreg16_write(WDOG1_BASE + IMX_WDOG_WSR, WSR_MAGIC2); 1160 #endif 1161 1162 } 1163 #endif 1164 1165 } 1166 #endif 1167 1168 1169 #if 0 1170 #include <arm/imx/imxgpiovar.h> 1171 1172 void gpio_test(void) 1173 void 1174 gpio_test(void) 1175 { 1176 int left, right; 1177 1178 gpio_set_direction(GPIO_NO(2, 22), GPIO_DIR_IN); 1179 gpio_set_direction(GPIO_NO(2, 23), GPIO_DIR_IN); 1180 1181 for (;;) { 1182 left = gpio_data_read(GPIO_NO(2, 22)); 1183 right = gpio_data_read(GPIO_NO(2, 23)); 1184 1185 printf("\r%s %s", 1186 left ? "off" : "ON ", 1187 right ? "off" : "ON "); 1188 } 1189 } 1190 #endif 1191