[BACK]Return to integrator_machdep.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / arch / evbarm / integrator

Annotation of src/sys/arch/evbarm/integrator/integrator_machdep.c, Revision 1.68.8.1

1.68.8.1! jdc         1: /*     $NetBSD: integrator_machdep.c,v 1.68 2011/07/01 20:39:34 dyoung Exp $   */
1.1       rearnsha    2:
                      3: /*
1.23      rearnsha    4:  * Copyright (c) 2001,2002 ARM Ltd
1.1       rearnsha    5:  * All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  * 3. The name of the company may not be used to endorse or promote
                     16:  *    products derived from this software without specific prior written
                     17:  *    permission.
                     18:  *
1.23      rearnsha   19:  * THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND
                     20:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     21:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     22:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL ARM LTD
                     23:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     24:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     25:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     26:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     27:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     28:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     29:  * POSSIBILITY OF SUCH DAMAGE.
                     30:  */
                     31:
                     32: /*
1.1       rearnsha   33:  * Copyright (c) 1997,1998 Mark Brinicombe.
                     34:  * Copyright (c) 1997,1998 Causality Limited.
                     35:  * All rights reserved.
                     36:  *
                     37:  * Redistribution and use in source and binary forms, with or without
                     38:  * modification, are permitted provided that the following conditions
                     39:  * are met:
                     40:  * 1. Redistributions of source code must retain the above copyright
                     41:  *    notice, this list of conditions and the following disclaimer.
                     42:  * 2. Redistributions in binary form must reproduce the above copyright
                     43:  *    notice, this list of conditions and the following disclaimer in the
                     44:  *    documentation and/or other materials provided with the distribution.
                     45:  * 3. All advertising materials mentioning features or use of this software
                     46:  *    must display the following acknowledgement:
                     47:  *     This product includes software developed by Mark Brinicombe
                     48:  *     for the NetBSD Project.
                     49:  * 4. The name of the company nor the name of the author may be used to
                     50:  *    endorse or promote products derived from this software without specific
                     51:  *    prior written permission.
                     52:  *
                     53:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
                     54:  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
                     55:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     56:  * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
                     57:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
                     58:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
                     59:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     60:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     61:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     62:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     63:  * SUCH DAMAGE.
                     64:  *
1.67      wiz        65:  * Machine dependent functions for kernel setup for integrator board
1.1       rearnsha   66:  *
                     67:  * Created      : 24/11/97
                     68:  */
1.43      lukem      69:
                     70: #include <sys/cdefs.h>
1.68.8.1! jdc        71: __KERNEL_RCSID(0, "$NetBSD: integrator_machdep.c,v 1.68 2011/07/01 20:39:34 dyoung Exp $");
1.1       rearnsha   72:
                     73: #include "opt_ddb.h"
                     74: #include "opt_pmap_debug.h"
                     75:
                     76: #include <sys/param.h>
                     77: #include <sys/device.h>
                     78: #include <sys/systm.h>
                     79: #include <sys/kernel.h>
                     80: #include <sys/exec.h>
                     81: #include <sys/proc.h>
                     82: #include <sys/msgbuf.h>
                     83: #include <sys/reboot.h>
                     84: #include <sys/termios.h>
1.32      ragge      85: #include <sys/ksyms.h>
1.1       rearnsha   86:
1.31      thorpej    87: #include <uvm/uvm_extern.h>
                     88:
1.1       rearnsha   89: #include <dev/cons.h>
                     90:
                     91: #include <machine/db_machdep.h>
                     92: #include <ddb/db_sym.h>
                     93: #include <ddb/db_extern.h>
                     94:
                     95: #include <machine/bootconfig.h>
1.68      dyoung     96: #include <sys/bus.h>
1.1       rearnsha   97: #include <machine/cpu.h>
                     98: #include <machine/frame.h>
                     99: #include <machine/intr.h>
1.6       thorpej   100: #include <arm/undefined.h>
1.1       rearnsha  101:
1.23      rearnsha  102: #include <arm/arm32/machdep.h>
                    103:
1.1       rearnsha  104: #include <evbarm/integrator/integrator_boot.h>
                    105:
                    106: #include "pci.h"
1.32      ragge     107: #include "ksyms.h"
1.1       rearnsha  108:
                    109: void ifpga_reset(void) __attribute__((noreturn));
1.36      thorpej   110:
                    111: /* Kernel text starts 2MB in from the bottom of the kernel address space. */
                    112: #define        KERNEL_TEXT_BASE        (KERNEL_BASE + 0x00200000)
1.39      thorpej   113: #define        KERNEL_VM_BASE          (KERNEL_BASE + 0x01000000)
1.40      thorpej   114:
                    115: /*
                    116:  * The range 0xc1000000 - 0xccffffff is available for kernel VM space
                    117:  * Core-logic registers and I/O mappings occupy 0xfd000000 - 0xffffffff
                    118:  */
                    119: #define KERNEL_VM_SIZE         0x0C000000
1.36      thorpej   120:
1.1       rearnsha  121: /*
                    122:  * Address to call from cpu_reset() to reset the machine.
1.67      wiz       123:  * This is machine architecture dependent as it varies depending
1.1       rearnsha  124:  * on where the ROM appears when you turn the MMU off.
                    125:  */
                    126:
                    127: u_int cpu_reset_address = (u_int) ifpga_reset;
                    128:
                    129: /* Define various stack sizes in pages */
                    130: #define IRQ_STACK_SIZE 1
                    131: #define ABT_STACK_SIZE 1
                    132: #define UND_STACK_SIZE 1
                    133:
                    134: BootConfig bootconfig;         /* Boot config storage */
                    135: char *boot_args = NULL;
                    136: char *boot_file = NULL;
                    137:
                    138: vm_offset_t physical_start;
                    139: vm_offset_t physical_end;
                    140:
                    141: /*int debug_flags;*/
                    142: #ifndef PMAP_STATIC_L1S
                    143: int max_processes = 64;                        /* Default number */
                    144: #endif /* !PMAP_STATIC_L1S */
                    145:
                    146: /* Physical and virtual addresses for some global pages */
                    147: pv_addr_t irqstack;
                    148: pv_addr_t undstack;
                    149: pv_addr_t abtstack;
                    150: pv_addr_t kernelstack;
                    151:
                    152: vm_offset_t msgbufphys;
                    153:
                    154: extern u_int data_abort_handler_address;
                    155: extern u_int prefetch_abort_handler_address;
                    156: extern u_int undefined_handler_address;
                    157:
                    158: #ifdef PMAP_DEBUG
                    159: extern int pmap_debug_level;
                    160: #endif
                    161:
1.23      rearnsha  162: #define KERNEL_PT_SYS          0       /* L2 table for mapping zero page */
                    163:
                    164: #define KERNEL_PT_KERNEL       1       /* L2 table for mapping kernel */
                    165: #define        KERNEL_PT_KERNEL_NUM    2
                    166:                                        /* L2 tables for mapping kernel VM */
                    167: #define KERNEL_PT_VMDATA       (KERNEL_PT_KERNEL + KERNEL_PT_KERNEL_NUM)
1.17      chris     168: #define        KERNEL_PT_VMDATA_NUM    4       /* start with 16MB of KVM */
1.1       rearnsha  169: #define NUM_KERNEL_PTS         (KERNEL_PT_VMDATA + KERNEL_PT_VMDATA_NUM)
                    170:
1.14      thorpej   171: pv_addr_t kernel_pt_table[NUM_KERNEL_PTS];
1.1       rearnsha  172:
                    173: /* Prototypes */
                    174:
1.23      rearnsha  175: static void    integrator_sdram_bounds (paddr_t *, psize_t *);
1.1       rearnsha  176:
1.23      rearnsha  177: void   consinit(void);
1.1       rearnsha  178:
                    179: /* A load of console goo. */
                    180: #include "vga.h"
1.23      rearnsha  181: #if NVGA > 0
1.1       rearnsha  182: #include <dev/ic/mc6845reg.h>
                    183: #include <dev/ic/pcdisplayvar.h>
                    184: #include <dev/ic/vgareg.h>
                    185: #include <dev/ic/vgavar.h>
                    186: #endif
                    187:
                    188: #include "pckbc.h"
1.23      rearnsha  189: #if NPCKBC > 0
1.1       rearnsha  190: #include <dev/ic/i8042reg.h>
                    191: #include <dev/ic/pckbcvar.h>
                    192: #endif
                    193:
                    194: #include "com.h"
1.23      rearnsha  195: #if NCOM > 0
1.1       rearnsha  196: #include <dev/ic/comreg.h>
                    197: #include <dev/ic/comvar.h>
                    198: #ifndef CONCOMADDR
                    199: #define CONCOMADDR 0x3f8
                    200: #endif
                    201: #endif
                    202:
1.23      rearnsha  203: /*
                    204:  * Define the default console speed for the board.  This is generally
                    205:  * what the firmware provided with the board defaults to.
                    206:  */
1.30      mycroft   207: #ifndef CONSPEED
1.1       rearnsha  208: #define CONSPEED B115200
                    209: #endif
                    210: #ifndef CONMODE
                    211: #define CONMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) /* 8N1 */
                    212: #endif
                    213:
                    214: int comcnspeed = CONSPEED;
                    215: int comcnmode = CONMODE;
                    216:
                    217: #include "plcom.h"
                    218: #if (NPLCOM > 0)
                    219: #include <evbarm/dev/plcomreg.h>
                    220: #include <evbarm/dev/plcomvar.h>
                    221:
                    222: #include <evbarm/ifpga/ifpgamem.h>
                    223: #include <evbarm/ifpga/ifpgareg.h>
                    224: #include <evbarm/ifpga/ifpgavar.h>
                    225: #endif
                    226:
                    227: #ifndef CONSDEVNAME
                    228: #define CONSDEVNAME "plcom"
                    229: #endif
                    230:
                    231: #ifndef PLCONSPEED
                    232: #define PLCONSPEED B38400
                    233: #endif
                    234: #ifndef PLCONMODE
                    235: #define PLCONMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) /* 8N1 */
                    236: #endif
                    237: #ifndef PLCOMCNUNIT
                    238: #define PLCOMCNUNIT -1
                    239: #endif
                    240:
                    241: int plcomcnspeed = PLCONSPEED;
                    242: int plcomcnmode = PLCONMODE;
                    243:
                    244: #if 0
                    245: extern struct consdev kcomcons;
                    246: static void kcomcnputc(dev_t, int);
                    247: #endif
                    248:
                    249: /*
                    250:  * void cpu_reboot(int howto, char *bootstr)
                    251:  *
                    252:  * Reboots the system
                    253:  *
                    254:  * Deal with any syncing, unmounting, dumping and shutdown hooks,
                    255:  * then reset the CPU.
                    256:  */
                    257: void
1.23      rearnsha  258: cpu_reboot(int howto, char *bootstr)
1.1       rearnsha  259: {
                    260:
                    261:        /*
                    262:         * If we are still cold then hit the air brakes
                    263:         * and crash to earth fast
                    264:         */
                    265:        if (cold) {
                    266:                doshutdownhooks();
1.59      dyoung    267:                pmf_system_shutdown(boothowto);
1.1       rearnsha  268:                printf("The operating system has halted.\n");
                    269:                printf("Please press any key to reboot.\n\n");
                    270:                cngetc();
                    271:                printf("rebooting...\n");
                    272:                ifpga_reset();
                    273:                /*NOTREACHED*/
                    274:        }
                    275:
                    276:        /* Disable console buffering */
                    277:
                    278:        /*
                    279:         * If RB_NOSYNC was not specified sync the discs.
1.23      rearnsha  280:         * Note: Unless cold is set to 1 here, syslogd will die during the
                    281:         * unmount.  It looks like syslogd is getting woken up only to find
                    282:         * that it cannot page part of the binary in as the filesystem has
                    283:         * been unmounted.
1.1       rearnsha  284:         */
                    285:        if (!(howto & RB_NOSYNC))
                    286:                bootsync();
                    287:
                    288:        /* Say NO to interrupts */
                    289:        splhigh();
                    290:
                    291:        /* Do a dump if requested. */
                    292:        if ((howto & (RB_DUMP | RB_HALT)) == RB_DUMP)
                    293:                dumpsys();
                    294:
                    295:        /* Run any shutdown hooks */
                    296:        doshutdownhooks();
                    297:
1.59      dyoung    298:        pmf_system_shutdown(boothowto);
                    299:
1.1       rearnsha  300:        /* Make sure IRQ's are disabled */
                    301:        IRQdisable;
                    302:
                    303:        if (howto & RB_HALT) {
                    304:                printf("The operating system has halted.\n");
                    305:                printf("Please press any key to reboot.\n\n");
                    306:                cngetc();
                    307:        }
                    308:
                    309:        printf("rebooting...\n");
                    310:        ifpga_reset();
                    311:        /*NOTREACHED*/
                    312: }
                    313:
1.42      thorpej   314: /* Statically mapped devices. */
                    315: static const struct pmap_devmap integrator_devmap[] = {
1.1       rearnsha  316: #if NPLCOM > 0 && defined(PLCONSOLE)
1.23      rearnsha  317:        {
                    318:                UART0_BOOT_BASE,
                    319:                IFPGA_IO_BASE + IFPGA_UART0,
                    320:                1024 * 1024,
                    321:                VM_PROT_READ|VM_PROT_WRITE,
                    322:                PTE_NOCACHE
                    323:        },
                    324:
                    325:        {
                    326:                UART1_BOOT_BASE,
                    327:                IFPGA_IO_BASE + IFPGA_UART1,
                    328:                1024 * 1024,
                    329:                VM_PROT_READ|VM_PROT_WRITE,
                    330:                PTE_NOCACHE
                    331:        },
1.1       rearnsha  332: #endif
                    333: #if NPCI > 0
1.23      rearnsha  334:        {
                    335:                IFPGA_PCI_IO_VBASE,
                    336:                IFPGA_PCI_IO_BASE,
                    337:                IFPGA_PCI_IO_VSIZE,
                    338:                VM_PROT_READ|VM_PROT_WRITE,
                    339:                PTE_NOCACHE
                    340:        },
                    341:
                    342:        {
                    343:                IFPGA_PCI_CONF_VBASE,
                    344:                IFPGA_PCI_CONF_BASE,
                    345:                IFPGA_PCI_CONF_VSIZE,
                    346:                VM_PROT_READ|VM_PROT_WRITE,
1.42      thorpej   347:                PTE_NOCACHE
                    348:        },
1.1       rearnsha  349: #endif
                    350:
1.23      rearnsha  351:        {
                    352:                0,
                    353:                0,
                    354:                0,
                    355:                0,
                    356:                0
                    357:        }
1.1       rearnsha  358: };
                    359:
                    360: /*
1.23      rearnsha  361:  * u_int initarm(...)
1.1       rearnsha  362:  *
                    363:  * Initial entry point on startup. This gets called before main() is
                    364:  * entered.
                    365:  * It should be responsible for setting up everything that must be
                    366:  * in place when main is called.
                    367:  * This includes
                    368:  *   Taking a copy of the boot configuration structure.
                    369:  *   Initialising the physical console so characters can be printed.
                    370:  *   Setting up page tables for the kernel
                    371:  *   Relocating the kernel to the bottom of physical memory
                    372:  */
                    373:
                    374: u_int
1.23      rearnsha  375: initarm(void *arg)
1.1       rearnsha  376: {
                    377:        int loop;
                    378:        int loop1;
                    379:        u_int l1pagetable;
1.55      perry     380:        extern char etext __asm ("_etext");
                    381:        extern char end __asm ("_end");
1.23      rearnsha  382:        paddr_t memstart;
                    383:        psize_t memsize;
1.47      rearnsha  384:        vm_offset_t physical_freestart;
                    385:        vm_offset_t physical_freeend;
1.1       rearnsha  386:
                    387:        /*
                    388:         * Heads up ... Setup the CPU / MMU / TLB functions
                    389:         */
                    390:        if (set_cpufuncs())
1.50      wiz       391:                panic("CPU not recognized!");
1.1       rearnsha  392:
                    393: #if NPLCOM > 0 && defined(PLCONSOLE)
                    394:        /*
                    395:         * Initialise the diagnostic serial console
                    396:         * This allows a means of generating output during initarm().
                    397:         * Once all the memory map changes are complete we can call consinit()
                    398:         * and not have to worry about things moving.
                    399:         */
                    400:
                    401:        if (PLCOMCNUNIT == 0) {
1.68.8.1! jdc       402:                static struct bus_space plcom_bus_space;
        !           403:                static struct plcom_instance ifpga_pi0 = {
        !           404:                        .pi_type = PLCOM_TYPE_PL010,
        !           405:                        .pi_iot = &plcom_bus_space,
        !           406:                        .pi_size = IFPGA_UART_SIZE,
        !           407:                        .pi_iobase = 0x0
        !           408:                };
        !           409:
1.1       rearnsha  410:                ifpga_create_io_bs_tag(&plcom_bus_space, (void*)0xfd600000);
1.68.8.1! jdc       411:                plcomcnattach(&ifpga_pi0, plcomcnspeed, IFPGA_UART_CLK,
        !           412:                    plcomcnmode, PLCOMCNUNIT);
1.1       rearnsha  413:        } else if (PLCOMCNUNIT == 1) {
1.68.8.1! jdc       414:                static struct bus_space plcom_bus_space;
        !           415:                static struct plcom_instance ifpga_pi1 = {
        !           416:                        .pi_type = PLCOM_TYPE_PL010,
        !           417:                        .pi_iot = &plcom_bus_space,
        !           418:                        .pi_size = IFPGA_UART_SIZE,
        !           419:                        .pi_iobase = 0x0
        !           420:                };
        !           421:
1.1       rearnsha  422:                ifpga_create_io_bs_tag(&plcom_bus_space, (void*)0xfd700000);
1.68.8.1! jdc       423:                plcomcnattach(&ifpga_pi1, plcomcnspeed, IFPGA_UART_CLK,
        !           424:                    plcomcnmode, PLCOMCNUNIT);
1.1       rearnsha  425:        }
                    426: #endif
                    427:
1.38      thorpej   428: #ifdef VERBOSE_INIT_ARM
1.1       rearnsha  429:        /* Talk to the user */
1.23      rearnsha  430:        printf("\nNetBSD/evbarm (Integrator) booting ...\n");
1.38      thorpej   431: #endif
1.1       rearnsha  432:
                    433:        /*
1.23      rearnsha  434:         * Fetch the SDRAM start/size from the CM configuration registers.
1.1       rearnsha  435:         */
1.23      rearnsha  436:        integrator_sdram_bounds(&memstart, &memsize);
1.1       rearnsha  437:
1.38      thorpej   438: #ifdef VERBOSE_INIT_ARM
1.1       rearnsha  439:        printf("initarm: Configuring system ...\n");
1.38      thorpej   440: #endif
1.1       rearnsha  441:
1.23      rearnsha  442:        /* Fake bootconfig structure for the benefit of pmap.c */
                    443:        /* XXX must make the memory description h/w independent */
                    444:        bootconfig.dramblocks = 1;
                    445:        bootconfig.dram[0].address = memstart;
1.31      thorpej   446:        bootconfig.dram[0].pages = memsize / PAGE_SIZE;
1.47      rearnsha  447:        bootconfig.dram[0].flags = BOOT_DRAM_CAN_DMA | BOOT_DRAM_PREFER;
1.23      rearnsha  448:
1.1       rearnsha  449:        /*
                    450:         * Set up the variables that define the availablilty of
1.23      rearnsha  451:         * physical memory.  For now, we're going to set
                    452:         * physical_freestart to 0x00200000 (where the kernel
                    453:         * was loaded), and allocate the memory we need downwards.
                    454:         * If we get too close to the L1 table that we set up, we
                    455:         * will panic.  We will update physical_freestart and
                    456:         * physical_freeend later to reflect what pmap_bootstrap()
                    457:         * wants to see.
                    458:         *
1.47      rearnsha  459:         * We assume that the kernel is loaded into bank[0].
                    460:         *
1.23      rearnsha  461:         * XXX pmap_bootstrap() needs an enema.
1.1       rearnsha  462:         */
1.23      rearnsha  463:        physical_start = bootconfig.dram[0].address;
1.47      rearnsha  464:        physical_end = 0;
1.1       rearnsha  465:
1.47      rearnsha  466:        /* Update the address of the first free 16KB chunk of physical memory */
                    467:        physical_freestart = ((uintptr_t) &end - KERNEL_BASE + PGOFSET)
                    468:            & ~PGOFSET;
                    469:        if (physical_freestart < bootconfig.dram[0].address)
                    470:                physical_freestart = bootconfig.dram[0].address;
                    471:        physical_freeend = bootconfig.dram[0].address +
                    472:            bootconfig.dram[0].pages * PAGE_SIZE;
                    473:
                    474:        for (loop = 0, physmem = 0; loop < bootconfig.dramblocks; loop++) {
                    475:                paddr_t memoryblock_end;
                    476:
                    477:                memoryblock_end = bootconfig.dram[loop].address +
                    478:                    bootconfig.dram[loop].pages * PAGE_SIZE;
                    479:                if (memoryblock_end > physical_end)
                    480:                        physical_end = memoryblock_end;
                    481:                if (bootconfig.dram[loop].address < physical_start)
                    482:                        physical_start = bootconfig.dram[loop].address;
                    483:
                    484:                physmem += bootconfig.dram[loop].pages;
                    485:        }
1.1       rearnsha  486:
1.38      thorpej   487: #ifdef VERBOSE_INIT_ARM
1.1       rearnsha  488:        /* Tell the user about the memory */
                    489:        printf("physmemory: %d pages at 0x%08lx -> 0x%08lx\n", physmem,
                    490:            physical_start, physical_end - 1);
1.38      thorpej   491: #endif
1.1       rearnsha  492:
                    493:        /*
1.23      rearnsha  494:         * Okay, the kernel starts 2MB in from the bottom of physical
                    495:         * memory.  We are going to allocate our bootstrap pages downwards
                    496:         * from there.
1.1       rearnsha  497:         *
1.23      rearnsha  498:         * We need to allocate some fixed page tables to get the kernel
                    499:         * going.  We allocate one page directory and a number of page
                    500:         * tables and store the physical addresses in the kernel_pt_table
                    501:         * array.
                    502:         *
                    503:         * The kernel page directory must be on a 16K boundary.  The page
1.53      abs       504:         * tables must be on 4K boundaries.  What we do is allocate the
1.23      rearnsha  505:         * page directory on the first 16K boundary that we encounter, and
                    506:         * the page tables on 4K boundaries otherwise.  Since we allocate
                    507:         * at least 3 L2 page tables, we are guaranteed to encounter at
                    508:         * least one 16K aligned region.
1.1       rearnsha  509:         */
                    510:
                    511: #ifdef VERBOSE_INIT_ARM
                    512:        printf("Allocating page tables\n");
                    513: #endif
                    514:
                    515: #ifdef VERBOSE_INIT_ARM
1.47      rearnsha  516:        printf("freestart = 0x%08lx, free pages = %d (0x%08x)\n",
                    517:               physical_freestart, physmem, physmem);
1.1       rearnsha  518: #endif
                    519:
                    520:        /* Define a macro to simplify memory allocation */
1.23      rearnsha  521: #define        valloc_pages(var, np)                           \
                    522:        alloc_pages((var).pv_pa, (np));                 \
1.47      rearnsha  523:        (var).pv_va = KERNEL_BASE + (var).pv_pa;
1.23      rearnsha  524:
                    525: #define alloc_pages(var, np)                           \
1.47      rearnsha  526:        (var) = physical_freestart;                     \
                    527:        physical_freestart += ((np) * PAGE_SIZE);       \
1.23      rearnsha  528:        if (physical_freeend < physical_freestart)      \
                    529:                panic("initarm: out of memory");        \
1.31      thorpej   530:        memset((char *)(var), 0, ((np) * PAGE_SIZE));
1.1       rearnsha  531:
                    532:        loop1 = 0;
                    533:        for (loop = 0; loop <= NUM_KERNEL_PTS; ++loop) {
                    534:                /* Are we 16KB aligned for an L1 ? */
1.47      rearnsha  535:                if ((physical_freestart & (L1_TABLE_SIZE - 1)) == 0
1.1       rearnsha  536:                    && kernel_l1pt.pv_pa == 0) {
1.31      thorpej   537:                        valloc_pages(kernel_l1pt, L1_TABLE_SIZE / PAGE_SIZE);
1.1       rearnsha  538:                } else {
1.33      thorpej   539:                        valloc_pages(kernel_pt_table[loop1],
                    540:                            L2_TABLE_SIZE / PAGE_SIZE);
1.23      rearnsha  541:                        ++loop1;
1.1       rearnsha  542:                }
                    543:        }
                    544:
                    545:        /* This should never be able to happen but better confirm that. */
1.21      thorpej   546:        if (!kernel_l1pt.pv_pa || (kernel_l1pt.pv_pa & (L1_TABLE_SIZE-1)) != 0)
1.28      provos    547:                panic("initarm: Failed to align the kernel page directory");
1.1       rearnsha  548:
                    549:        /*
                    550:         * Allocate a page for the system page mapped to V0x00000000
                    551:         * This page will just contain the system vectors and can be
                    552:         * shared by all processes.
                    553:         */
                    554:        alloc_pages(systempage.pv_pa, 1);
                    555:
                    556:        /* Allocate stacks for all modes */
                    557:        valloc_pages(irqstack, IRQ_STACK_SIZE);
                    558:        valloc_pages(abtstack, ABT_STACK_SIZE);
                    559:        valloc_pages(undstack, UND_STACK_SIZE);
                    560:        valloc_pages(kernelstack, UPAGES);
                    561:
                    562: #ifdef VERBOSE_INIT_ARM
1.23      rearnsha  563:        printf("IRQ stack: p0x%08lx v0x%08lx\n", irqstack.pv_pa,
                    564:            irqstack.pv_va);
                    565:        printf("ABT stack: p0x%08lx v0x%08lx\n", abtstack.pv_pa,
                    566:            abtstack.pv_va);
                    567:        printf("UND stack: p0x%08lx v0x%08lx\n", undstack.pv_pa,
                    568:            undstack.pv_va);
                    569:        printf("SVC stack: p0x%08lx v0x%08lx\n", kernelstack.pv_pa,
                    570:            kernelstack.pv_va);
1.1       rearnsha  571: #endif
                    572:
1.31      thorpej   573:        alloc_pages(msgbufphys, round_page(MSGBUFSIZE) / PAGE_SIZE);
1.1       rearnsha  574:
                    575:        /*
                    576:         * Ok we have allocated physical pages for the primary kernel
                    577:         * page tables
                    578:         */
                    579:
                    580: #ifdef VERBOSE_INIT_ARM
1.23      rearnsha  581:        printf("Creating L1 page table at 0x%08lx\n", kernel_l1pt.pv_pa);
1.1       rearnsha  582: #endif
                    583:
                    584:        /*
1.23      rearnsha  585:         * Now we start construction of the L1 page table
1.1       rearnsha  586:         * We start by mapping the L2 page tables into the L1.
                    587:         * This means that we can replace L1 mappings later on if necessary
                    588:         */
                    589:        l1pagetable = kernel_l1pt.pv_pa;
                    590:
                    591:        /* Map the L2 pages tables in the L1 page table */
1.11      thorpej   592:        pmap_link_l2pt(l1pagetable, 0x00000000,
1.14      thorpej   593:            &kernel_pt_table[KERNEL_PT_SYS]);
1.23      rearnsha  594:        for (loop = 0; loop < KERNEL_PT_KERNEL_NUM; loop++)
                    595:                pmap_link_l2pt(l1pagetable, KERNEL_BASE + loop * 0x00400000,
                    596:                    &kernel_pt_table[KERNEL_PT_KERNEL + loop]);
                    597:        for (loop = 0; loop < KERNEL_PT_VMDATA_NUM; loop++)
1.11      thorpej   598:                pmap_link_l2pt(l1pagetable, KERNEL_VM_BASE + loop * 0x00400000,
1.14      thorpej   599:                    &kernel_pt_table[KERNEL_PT_VMDATA + loop]);
1.17      chris     600:
                    601:        /* update the top of the kernel VM */
1.19      thorpej   602:        pmap_curmaxkvaddr =
                    603:            KERNEL_VM_BASE + (KERNEL_PT_VMDATA_NUM * 0x00400000);
1.1       rearnsha  604:
                    605: #ifdef VERBOSE_INIT_ARM
                    606:        printf("Mapping kernel\n");
                    607: #endif
                    608:
                    609:        /* Now we fill in the L2 pagetable for the kernel static code/data */
                    610:        {
                    611:                size_t textsize = (uintptr_t) &etext - KERNEL_TEXT_BASE;
                    612:                size_t totalsize = (uintptr_t) &end - KERNEL_TEXT_BASE;
1.23      rearnsha  613:                u_int logical;
1.1       rearnsha  614:
1.23      rearnsha  615:                textsize = (textsize + PGOFSET) & ~PGOFSET;
1.1       rearnsha  616:                totalsize = (totalsize + PGOFSET) & ~PGOFSET;
1.23      rearnsha  617:
                    618:                logical = 0x00200000;   /* offset of kernel in RAM */
                    619:
                    620:                logical += pmap_map_chunk(l1pagetable, KERNEL_BASE + logical,
1.47      rearnsha  621:                    logical, textsize, VM_PROT_READ | VM_PROT_WRITE,
                    622:                    PTE_CACHE);
1.23      rearnsha  623:                logical += pmap_map_chunk(l1pagetable, KERNEL_BASE + logical,
1.47      rearnsha  624:                    logical, totalsize - textsize,
                    625:                    VM_PROT_READ | VM_PROT_WRITE, PTE_CACHE);
1.1       rearnsha  626:        }
                    627:
                    628: #ifdef VERBOSE_INIT_ARM
                    629:        printf("Constructing L2 page tables\n");
                    630: #endif
                    631:
                    632:        /* Map the stack pages */
1.14      thorpej   633:        pmap_map_chunk(l1pagetable, irqstack.pv_va, irqstack.pv_pa,
1.31      thorpej   634:            IRQ_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
1.14      thorpej   635:        pmap_map_chunk(l1pagetable, abtstack.pv_va, abtstack.pv_pa,
1.31      thorpej   636:            ABT_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
1.14      thorpej   637:        pmap_map_chunk(l1pagetable, undstack.pv_va, undstack.pv_pa,
1.31      thorpej   638:            UND_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
1.14      thorpej   639:        pmap_map_chunk(l1pagetable, kernelstack.pv_va, kernelstack.pv_pa,
1.31      thorpej   640:            UPAGES * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
1.13      thorpej   641:
1.33      thorpej   642:        pmap_map_chunk(l1pagetable, kernel_l1pt.pv_va, kernel_l1pt.pv_pa,
                    643:            L1_TABLE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_PAGETABLE);
1.1       rearnsha  644:
1.33      thorpej   645:        for (loop = 0; loop < NUM_KERNEL_PTS; ++loop) {
                    646:                pmap_map_chunk(l1pagetable, kernel_pt_table[loop].pv_va,
1.44      rearnsha  647:                    kernel_pt_table[loop].pv_pa, L2_TABLE_SIZE,
1.33      thorpej   648:                    VM_PROT_READ|VM_PROT_WRITE, PTE_PAGETABLE);
                    649:        }
1.1       rearnsha  650:
1.20      thorpej   651:        /* Map the vector page. */
1.1       rearnsha  652: #if 1
                    653:        /* MULTI-ICE requires that page 0 is NC/NB so that it can download
                    654:           the cache-clean code there.  */
1.51      rearnsha  655:        pmap_map_entry(l1pagetable, ARM_VECTORS_LOW, systempage.pv_pa,
1.10      thorpej   656:            VM_PROT_READ|VM_PROT_WRITE, PTE_NOCACHE);
1.1       rearnsha  657: #else
1.51      rearnsha  658:        pmap_map_entry(l1pagetable, ARM_VECTORS_LOW, systempage.pv_pa,
1.20      thorpej   659:            VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
1.1       rearnsha  660: #endif
                    661:
1.42      thorpej   662:        /* Map the statically mapped devices. */
                    663:        pmap_devmap_bootstrap(l1pagetable, integrator_devmap);
1.1       rearnsha  664:
                    665:        /*
                    666:         * Now we have the real page tables in place so we can switch to them.
1.23      rearnsha  667:         * Once this is done we will be running with the REAL kernel page
                    668:         * tables.
                    669:         */
                    670:
1.1       rearnsha  671:        /* Switch tables */
                    672: #ifdef VERBOSE_INIT_ARM
                    673:        printf("switching to new L1 page table  @%#lx...", kernel_l1pt.pv_pa);
                    674: #endif
1.33      thorpej   675:        cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT);
1.66      uebayasi  676:        cpu_setttb(kernel_l1pt.pv_pa);
1.23      rearnsha  677:        cpu_tlb_flushID();
1.33      thorpej   678:        cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2));
                    679:
                    680:        /*
                    681:         * Moved from cpu_startup() as data_abort_handler() references
                    682:         * this during uvm init
                    683:         */
1.64      rmind     684:        uvm_lwp_setuarea(&lwp0, kernelstack.pv_va);
1.1       rearnsha  685:
                    686: #ifdef PLCONSOLE
                    687:        /*
                    688:         * The IFPGA registers have just moved.
                    689:         * Detach the diagnostic serial port and reattach at the new address.
                    690:         */
                    691:        plcomcndetach();
                    692: #endif
                    693:
                    694:        /*
                    695:         * XXX this should only be done in main() but it useful to
                    696:         * have output earlier ...
                    697:         */
                    698:        consinit();
                    699:
                    700: #ifdef VERBOSE_INIT_ARM
                    701:        printf("bootstrap done.\n");
                    702: #endif
                    703:
1.20      thorpej   704:        arm32_vector_init(ARM_VECTORS_LOW, ARM_VEC_ALL);
1.1       rearnsha  705:
                    706:        /*
                    707:         * Pages were allocated during the secondary bootstrap for the
                    708:         * stacks for different CPU modes.
                    709:         * We must now set the r13 registers in the different CPU modes to
                    710:         * point to these stacks.
                    711:         * Since the ARM stacks use STMFD etc. we must set r13 to the top end
                    712:         * of the stack memory.
                    713:         */
1.38      thorpej   714: #ifdef VERBOSE_INIT_ARM
1.1       rearnsha  715:        printf("init subsystems: stacks ");
1.38      thorpej   716: #endif
1.1       rearnsha  717:
1.31      thorpej   718:        set_stackptr(PSR_IRQ32_MODE,
                    719:            irqstack.pv_va + IRQ_STACK_SIZE * PAGE_SIZE);
                    720:        set_stackptr(PSR_ABT32_MODE,
                    721:            abtstack.pv_va + ABT_STACK_SIZE * PAGE_SIZE);
                    722:        set_stackptr(PSR_UND32_MODE,
                    723:            undstack.pv_va + UND_STACK_SIZE * PAGE_SIZE);
1.1       rearnsha  724:
                    725:        /*
                    726:         * Well we should set a data abort handler.
1.23      rearnsha  727:         * Once things get going this will change as we will need a proper
                    728:         * handler.
1.1       rearnsha  729:         * Until then we will use a handler that just panics but tells us
                    730:         * why.
                    731:         * Initialisation of the vectors will just panic on a data abort.
1.52      abs       732:         * This just fills in a slightly better one.
1.1       rearnsha  733:         */
1.38      thorpej   734: #ifdef VERBOSE_INIT_ARM
1.1       rearnsha  735:        printf("vectors ");
1.38      thorpej   736: #endif
1.1       rearnsha  737:        data_abort_handler_address = (u_int)data_abort_handler;
                    738:        prefetch_abort_handler_address = (u_int)prefetch_abort_handler;
                    739:        undefined_handler_address = (u_int)undefinedinstruction_bounce;
                    740:
                    741:        /* Initialise the undefined instruction handlers */
1.38      thorpej   742: #ifdef VERBOSE_INIT_ARM
1.1       rearnsha  743:        printf("undefined ");
1.38      thorpej   744: #endif
1.1       rearnsha  745:        undefined_init();
                    746:
1.25      thorpej   747:        /* Load memory into UVM. */
1.38      thorpej   748: #ifdef VERBOSE_INIT_ARM
1.25      thorpej   749:        printf("page ");
1.38      thorpej   750: #endif
1.25      thorpej   751:        uvm_setpagesize();      /* initialize PAGE_SIZE-dependent variables */
1.47      rearnsha  752:
                    753:        /* Round the start up and the end down to a page.  */
                    754:        physical_freestart = (physical_freestart + PGOFSET) & ~PGOFSET;
                    755:        physical_freeend &= ~PGOFSET;
                    756:
                    757:        for (loop = 0; loop < bootconfig.dramblocks; loop++) {
                    758:                paddr_t block_start = (paddr_t) bootconfig.dram[loop].address;
                    759:                paddr_t block_end = block_start +
                    760:                    (bootconfig.dram[loop].pages * PAGE_SIZE);
                    761:
                    762:                if (loop == 0) {
                    763:                        block_start = physical_freestart;
                    764:                        block_end = physical_freeend;
                    765:                }
                    766:
                    767:
                    768:                uvm_page_physload(atop(block_start), atop(block_end),
                    769:                    atop(block_start), atop(block_end),
                    770:                    (bootconfig.dram[loop].flags & BOOT_DRAM_PREFER) ?
                    771:                    VM_FREELIST_DEFAULT : VM_FREELIST_DEFAULT + 1);
                    772:        }
1.25      thorpej   773:
1.1       rearnsha  774:        /* Boot strap pmap telling it where the kernel page table is */
1.38      thorpej   775: #ifdef VERBOSE_INIT_ARM
1.1       rearnsha  776:        printf("pmap ");
1.38      thorpej   777: #endif
1.58      matt      778:        pmap_bootstrap(KERNEL_VM_BASE, KERNEL_VM_BASE + KERNEL_VM_SIZE);
1.1       rearnsha  779:
                    780:        /* Setup the IRQ system */
1.38      thorpej   781: #ifdef VERBOSE_INIT_ARM
1.1       rearnsha  782:        printf("irq ");
1.38      thorpej   783: #endif
1.48      rearnsha  784:        ifpga_intr_init();
1.1       rearnsha  785:
1.38      thorpej   786: #ifdef VERBOSE_INIT_ARM
1.1       rearnsha  787:        printf("done.\n");
1.38      thorpej   788: #endif
1.1       rearnsha  789:
                    790: #ifdef DDB
                    791:        db_machine_init();
                    792:        if (boothowto & RB_KDB)
                    793:                Debugger();
                    794: #endif
                    795:
                    796:        /* We return the new stack pointer address */
                    797:        return(kernelstack.pv_va + USPACE_SVC_STACK_TOP);
                    798: }
                    799:
                    800: void
                    801: consinit(void)
                    802: {
                    803:        static int consinit_called = 0;
                    804: #if 0
                    805:        char *console = CONSDEVNAME;
                    806: #endif
                    807:
                    808:        if (consinit_called != 0)
                    809:                return;
                    810:
                    811:        consinit_called = 1;
                    812:
                    813: #if NPLCOM > 0 && defined(PLCONSOLE)
                    814:        if (PLCOMCNUNIT == 0) {
1.68.8.1! jdc       815:                static struct bus_space plcom_bus_space;
        !           816:                static struct plcom_instance ifpga_pi1 = {
        !           817:                        .pi_type = PLCOM_TYPE_PL010,
        !           818:                        .pi_iot = &plcom_bus_space,
        !           819:                        .pi_size = IFPGA_UART_SIZE,
        !           820:                        .pi_iobase = 0x0
        !           821:                };
        !           822:
1.1       rearnsha  823:                ifpga_create_io_bs_tag(&plcom_bus_space,
                    824:                    (void*)UART0_BOOT_BASE);
1.68.8.1! jdc       825:
        !           826:                if (plcomcnattach(&ifpga_pi1, plcomcnspeed, IFPGA_UART_CLK,
        !           827:                      plcomcnmode, PLCOMCNUNIT))
1.1       rearnsha  828:                        panic("can't init serial console");
                    829:                return;
                    830:        } else if (PLCOMCNUNIT == 1) {
1.68.8.1! jdc       831:                static struct bus_space plcom_bus_space;
        !           832:                static struct plcom_instance ifpga_pi1 = {
        !           833:                        .pi_type = PLCOM_TYPE_PL010,
        !           834:                        .pi_iot = &plcom_bus_space,
        !           835:                        .pi_size = IFPGA_UART_SIZE,
        !           836:                        .pi_iobase = 0x0
        !           837:                };
        !           838:
1.1       rearnsha  839:                ifpga_create_io_bs_tag(&plcom_bus_space,
                    840:                    (void*)UART0_BOOT_BASE);
1.68.8.1! jdc       841:
        !           842:                if (plcomcnattach(&ifpga_pi1, plcomcnspeed, IFPGA_UART_CLK,
        !           843:                      plcomcnmode, PLCOMCNUNIT))
1.1       rearnsha  844:                        panic("can't init serial console");
                    845:                return;
                    846:        }
                    847: #endif
                    848: #if (NCOM > 0)
                    849:        if (comcnattach(&isa_io_bs_tag, CONCOMADDR, comcnspeed,
1.41      thorpej   850:            COM_FREQ, COM_TYPE_NORMAL, comcnmode))
1.1       rearnsha  851:                panic("can't init serial console @%x", CONCOMADDR);
                    852:        return;
                    853: #endif
                    854:        panic("No serial console configured");
1.23      rearnsha  855: }
                    856:
                    857: static void
                    858: integrator_sdram_bounds(paddr_t *memstart, psize_t *memsize)
                    859: {
                    860:        volatile unsigned long *cm_sdram
                    861:            = (volatile unsigned long *)0x10000020;
1.46      rearnsha  862:        volatile unsigned long *cm_stat
                    863:            = (volatile unsigned long *)0x10000010;
1.23      rearnsha  864:
1.46      rearnsha  865:        *memstart = *cm_stat & 0x00ff0000;
1.23      rearnsha  866:
1.46      rearnsha  867:        /*
                    868:         * Although the SSRAM overlaps the SDRAM, we can use the wrap-around
                    869:         * to access the entire bank.
                    870:         */
1.23      rearnsha  871:        switch ((*cm_sdram >> 2) & 0x7)
                    872:        {
                    873:        case 0:
                    874:                *memsize = 16 * 1024 * 1024;
                    875:                break;
                    876:        case 1:
                    877:                *memsize = 32 * 1024 * 1024;
                    878:                break;
                    879:        case 2:
                    880:                *memsize = 64 * 1024 * 1024;
                    881:                break;
                    882:        case 3:
                    883:                *memsize = 128 * 1024 * 1024;
                    884:                break;
                    885:        case 4:
1.46      rearnsha  886:                /* With 256M of memory there is no wrap-around.  */
                    887:                *memsize = 256 * 1024 * 1024 - *memstart;
1.23      rearnsha  888:                break;
                    889:        default:
                    890:                printf("CM_SDRAM retuns unknown value, using 16M\n");
                    891:                *memsize = 16 * 1024 * 1024;
                    892:                break;
                    893:        }
1.1       rearnsha  894: }

CVSweb <webmaster@jp.NetBSD.org>