Author: gonzo Date: Wed Aug 15 06:06:43 2012 New Revision: 239280 URL: http://svn.freebsd.org/changeset/base/239280
Log: Merging of projects/armv6, part 9 Very basic support for Nvidia Tegra2: timer, interrupts, UART. Submitted by: Damjan Marion <dmar...@freebsd.org> Added: head/sys/arm/tegra/ head/sys/arm/tegra/bus_space.c (contents, props changed) head/sys/arm/tegra/common.c (contents, props changed) head/sys/arm/tegra/files.tegra2 (contents, props changed) head/sys/arm/tegra/std.tegra2 (contents, props changed) head/sys/arm/tegra/tegra2_machdep.c (contents, props changed) head/sys/boot/fdt/dts/trimslice.dts (contents, props changed) Added: head/sys/arm/tegra/bus_space.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/arm/tegra/bus_space.c Wed Aug 15 06:06:43 2012 (r239280) @@ -0,0 +1,153 @@ +/*- + * Copyright (c) 2012 Damjan Marion <damjan.mar...@gmail.com> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/kernel.h> +#include <sys/malloc.h> + +#include <machine/bus.h> + +/* Prototypes for all the bus_space structure functions */ +bs_protos(generic); +bs_protos(generic_armv4); + +/* + * The bus space tag. This is constant for all instances, so + * we never have to explicitly "create" it. + */ +static struct bus_space _base_tag = { + /* cookie */ + (void *) 0, + + /* mapping/unmapping */ + generic_bs_map, + generic_bs_unmap, + generic_bs_subregion, + + /* allocation/deallocation */ + generic_bs_alloc, + generic_bs_free, + + /* barrier */ + generic_bs_barrier, + + /* read (single) */ + generic_bs_r_1, + generic_armv4_bs_r_2, + generic_bs_r_4, + NULL, + + /* read multiple */ + generic_bs_rm_1, + generic_armv4_bs_rm_2, + generic_bs_rm_4, + NULL, + + /* read region */ + generic_bs_rr_1, + generic_armv4_bs_rr_2, + generic_bs_rr_4, + NULL, + + /* write (single) */ + generic_bs_w_1, + generic_armv4_bs_w_2, + generic_bs_w_4, + NULL, + + /* write multiple */ + generic_bs_wm_1, + generic_armv4_bs_wm_2, + generic_bs_wm_4, + NULL, + + /* write region */ + NULL, + NULL, + NULL, + NULL, + + /* set multiple */ + NULL, + NULL, + NULL, + NULL, + + /* set region */ + NULL, + NULL, + NULL, + NULL, + + /* copy */ + NULL, + NULL, + NULL, + NULL, + + /* read stream (single) */ + NULL, + NULL, + NULL, + NULL, + + /* read multiple stream */ + NULL, + generic_armv4_bs_rm_2, /* bus_space_read_multi_stream_2 */ + NULL, + NULL, + + /* read region stream */ + NULL, + NULL, + NULL, + NULL, + + /* write stream (single) */ + NULL, + NULL, + NULL, + NULL, + + /* write multiple stream */ + NULL, + generic_armv4_bs_wm_2, /* bus_space_write_multi_stream_2 */ + NULL, + NULL, + + /* write region stream */ + NULL, + NULL, + NULL, + NULL +}; + +bus_space_tag_t fdtbus_bs_tag = &_base_tag; Added: head/sys/arm/tegra/common.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/arm/tegra/common.c Wed Aug 15 06:06:43 2012 (r239280) @@ -0,0 +1,78 @@ +/*- + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * + * Developed by Damjan Marion <damjan.mar...@gmail.com> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/kernel.h> + +#include <dev/fdt/fdt_common.h> +#include <dev/ofw/openfirm.h> + +#include <machine/bus.h> +#include <machine/fdt.h> + +/* FIXME move to header file */ +#define TEGRA2_CLK_RST_PA_BASE 0x60006000 + +void +cpu_reset(void) +{ + bus_space_handle_t bsh; + printf("Restetting...\n"); + bus_space_map(fdtbus_bs_tag,TEGRA2_CLK_RST_PA_BASE, 0x1000, 0, &bsh); + bus_space_write_4(fdtbus_bs_tag, bsh, 4, 4); +} + +struct fdt_fixup_entry fdt_fixup_table[] = { + { NULL, NULL } +}; + +static int +fdt_pic_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig, + int *pol) +{ + if (!fdt_is_compatible(node, "arm,gic")) + return (ENXIO); + + *interrupt = fdt32_to_cpu(intr[0]); + *trig = INTR_TRIGGER_CONFORM; + *pol = INTR_POLARITY_CONFORM; + return (0); +} + +fdt_pic_decode_t fdt_pic_table[] = { + &fdt_pic_decode_ic, + NULL +}; + + + Added: head/sys/arm/tegra/files.tegra2 ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/arm/tegra/files.tegra2 Wed Aug 15 06:06:43 2012 (r239280) @@ -0,0 +1,19 @@ +# $FreeBSD$ + +arm/arm/bus_space_asm_generic.S standard +arm/arm/bus_space_generic.c standard +arm/arm/cpufunc_asm_armv5.S standard +arm/arm/cpufunc_asm_arm11.S standard +arm/arm/cpufunc_asm_armv7.S standard +arm/arm/irq_dispatch.S standard + +arm/arm/gic.c standard +arm/arm/mpcore_timer.c standard + +arm/tegra/bus_space.c standard +arm/tegra/common.c standard +arm/tegra/tegra2_machdep.c standard + +kern/kern_clocksource.c standard + +dev/uart/uart_dev_ns8250.c optional uart Added: head/sys/arm/tegra/std.tegra2 ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/arm/tegra/std.tegra2 Wed Aug 15 06:06:43 2012 (r239280) @@ -0,0 +1,16 @@ +# nVidia Tegra 2 common options +#$FreeBSD$ + +cpu CPU_CORTEXA +makeoption ARM_LITTLE_ENDIAN + +options PHYSADDR=0x00000000 + +makeoptions KERNPHYSADDR=0x00200000 +options KERNPHYSADDR=0x00200000 +makeoptions KERNVIRTADDR=0xc0200000 +options KERNVIRTADDR=0xc0200000 + +options STARTUP_PAGETABLE_ADDR=0x00100000 + +files "../tegra/files.tegra2" Added: head/sys/arm/tegra/tegra2_machdep.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/arm/tegra/tegra2_machdep.c Wed Aug 15 06:06:43 2012 (r239280) @@ -0,0 +1,705 @@ +/*- + * Copyright (c) 2011 Damjan Marion. + * Copyright (c) 1994-1998 Mark Brinicombe. + * Copyright (c) 1994 Brini. + * All rights reserved. + * + * This code is derived from software written for Brini by Mark Brinicombe + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: FreeBSD: //depot/projects/arm/src/sys/arm/mv/mv_machdep.c + */ + +#include "opt_ddb.h" +#include "opt_platform.h" + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#define _ARM32_BUS_DMA_PRIVATE +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/sysproto.h> +#include <sys/signalvar.h> +#include <sys/imgact.h> +#include <sys/kernel.h> +#include <sys/ktr.h> +#include <sys/linker.h> +#include <sys/lock.h> +#include <sys/malloc.h> +#include <sys/mutex.h> +#include <sys/pcpu.h> +#include <sys/proc.h> +#include <sys/ptrace.h> +#include <sys/cons.h> +#include <sys/bio.h> +#include <sys/bus.h> +#include <sys/buf.h> +#include <sys/exec.h> +#include <sys/kdb.h> +#include <sys/msgbuf.h> +#include <machine/reg.h> +#include <machine/cpu.h> + +#include <dev/fdt/fdt_common.h> +#include <dev/ofw/openfirm.h> + +#include <vm/vm.h> +#include <vm/pmap.h> +#include <vm/vm_object.h> +#include <vm/vm_page.h> +#include <vm/vm_pager.h> +#include <vm/vm_map.h> +#include <vm/vnode_pager.h> +#include <machine/pmap.h> +#include <machine/vmparam.h> +#include <machine/pcb.h> +#include <machine/undefined.h> +#include <machine/machdep.h> +#include <machine/metadata.h> +#include <machine/armreg.h> +#include <machine/bus.h> +#include <sys/reboot.h> + +/* FIXME move to tegrareg.h */ +#define TEGRA2_BASE 0xE0000000 /* KVM base for peripherials */ +#define TEGRA2_UARTA_VA_BASE 0xE1006000 +#define TEGRA2_UARTA_PA_BASE 0x70006000 + + + + + +#define KERNEL_PT_MAX 78 +#define IRQ_STACK_SIZE 1 +#define ABT_STACK_SIZE 1 +#define UND_STACK_SIZE 1 +#define FIQ_STACK_SIZE 1 + +#define PTE_DEVICE 3 + +#define debugf(fmt, args...) printf(fmt, ##args) + +#define KERNEL_PT_SYS 0 /* Page table for mapping proc0 zero page */ +#define KERNEL_PT_KERN 1 +#define KERNEL_PT_KERN_NUM 22 +#define KERNEL_PT_AFKERNEL KERNEL_PT_KERN + KERNEL_PT_KERN_NUM /* L2 table for mapping after kernel */ +#define KERNEL_PT_AFKERNEL_NUM 5 + +/* this should be evenly divisable by PAGE_SIZE / L2_TABLE_SIZE_REAL (or 4) */ +#define NUM_KERNEL_PTS (KERNEL_PT_AFKERNEL + KERNEL_PT_AFKERNEL_NUM) + +#ifdef DDB +extern vm_offset_t ksym_start, ksym_end; +#endif + + +extern unsigned char kernbase[]; +extern unsigned char _etext[]; +extern unsigned char _edata[]; +extern unsigned char __bss_start[]; +extern unsigned char _end[]; + +extern u_int data_abort_handler_address; +extern u_int prefetch_abort_handler_address; +extern u_int undefined_handler_address; + +struct pv_addr kernel_pt_table[KERNEL_PT_MAX]; + + + +static struct pv_addr kernel_l1pt; /* Level-1 page table entry */ + +/* Physical and virtual addresses for some global pages */ + +vm_paddr_t phys_avail[10]; +vm_paddr_t dump_avail[4]; + +static struct mem_region availmem_regions[FDT_MEM_REGIONS]; +static int availmem_regions_sz; + +extern vm_offset_t pmap_bootstrap_lastaddr; + +vm_offset_t pmap_bootstrap_lastaddr; + +const struct pmap_devmap *pmap_devmap_bootstrap_table; +struct pv_addr systempage; +struct pv_addr msgbufpv; +static struct pv_addr fiqstack; +static struct pv_addr irqstack; +static struct pv_addr undstack; +static struct pv_addr abtstack; +static struct pv_addr kernelstack; + +#define PHYS2VIRT(x) ((x - KERNPHYSADDR) + KERNVIRTADDR) +#define VIRT2PHYS(x) ((x - KERNVIRTADDR) + KERNPHYSADDR) + +static int platform_devmap_init(void); + +static char * +kenv_next(char *cp) +{ + + if (cp != NULL) { + while (*cp != 0) + cp++; + cp++; + if (*cp == 0) + cp = NULL; + } + return (cp); +} + + +/* + * Early Print + */ + +#define DEBUGBUF_SIZE 256 +#define LSR_THRE 0x20 /* Xmit holding register empty */ +#define EARLY_UART_VA_BASE TEGRA2_UARTA_VA_BASE +#define EARLY_UART_PA_BASE TEGRA2_UARTA_PA_BASE +char debugbuf[DEBUGBUF_SIZE]; + +void early_putstr(unsigned char *str) +{ + volatile uint8_t *p_lsr = (volatile uint8_t*) (EARLY_UART_VA_BASE + 0x14); + volatile uint8_t *p_thr = (volatile uint8_t*) (EARLY_UART_VA_BASE + 0x00); + + do { + while ((*p_lsr & LSR_THRE) == 0); + *p_thr = *str; + + if (*str == '\n') + { + while ((*p_lsr & LSR_THRE) == 0); + *p_thr = '\r'; + } + } while (*++str != '\0'); +} + +#if (STARTUP_PAGETABLE_ADDR < PHYSADDR) || \ + (STARTUP_PAGETABLE_ADDR > (PHYSADDR + (64 * 1024 * 1024))) +#error STARTUP_PAGETABLE_ADDR is not within init. MMU table, early print support not possible +#endif + +void +early_print_init(void) +{ + volatile uint32_t *mmu_tbl = (volatile uint32_t*)STARTUP_PAGETABLE_ADDR; + mmu_tbl[(EARLY_UART_VA_BASE >> L1_S_SHIFT)] = L1_TYPE_S | L1_S_AP(AP_KRW) | (EARLY_UART_PA_BASE & L1_S_FRAME); + __asm __volatile ("mcr p15, 0, r0, c8, c7, 0"); /* invalidate I+D TLBs */ + __asm __volatile ("mcr p15, 0, r0, c7, c10, 4"); /* drain the write buffer */ + early_putstr("Early printf initialise\n"); +} + +#define EPRINTF(args...) \ + snprintf(debugbuf,DEBUGBUF_SIZE, ##args ); \ + early_putstr(debugbuf); + +static void +print_kenv(void) +{ + int len; + char *cp; + + debugf("loader passed (static) kenv:\n"); + if (kern_envp == NULL) { + debugf(" no env, null ptr\n"); + return; + } + debugf(" kern_envp = 0x%08x\n", (uint32_t)kern_envp); + + len = 0; + for (cp = kern_envp; cp != NULL; cp = kenv_next(cp)) + debugf(" %x %s\n", (uint32_t)cp, cp); +} + +static void +print_kernel_section_addr(void) +{ + + debugf("kernel image addresses:\n"); + debugf(" kernbase = 0x%08x\n", (uint32_t)kernbase); + debugf(" _etext (sdata) = 0x%08x\n", (uint32_t)_etext); + debugf(" _edata = 0x%08x\n", (uint32_t)_edata); + debugf(" __bss_start = 0x%08x\n", (uint32_t)__bss_start); + debugf(" _end = 0x%08x\n", (uint32_t)_end); +} + +static void +physmap_init(void) +{ + int i, j, cnt; + vm_offset_t phys_kernelend, kernload; + uint32_t s, e, sz; + struct mem_region *mp, *mp1; + + phys_kernelend = KERNPHYSADDR + (virtual_avail - KERNVIRTADDR); + kernload = KERNPHYSADDR; + + /* + * Remove kernel physical address range from avail + * regions list. Page align all regions. + * Non-page aligned memory isn't very interesting to us. + * Also, sort the entries for ascending addresses. + */ + sz = 0; + cnt = availmem_regions_sz; + debugf("processing avail regions:\n"); + for (mp = availmem_regions; mp->mr_size; mp++) { + s = mp->mr_start; + e = mp->mr_start + mp->mr_size; + debugf(" %08x-%08x -> ", s, e); + /* Check whether this region holds all of the kernel. */ + if (s < kernload && e > phys_kernelend) { + availmem_regions[cnt].mr_start = phys_kernelend; + availmem_regions[cnt++].mr_size = e - phys_kernelend; + e = kernload; + } + /* Look whether this regions starts within the kernel. */ + if (s >= kernload && s < phys_kernelend) { + if (e <= phys_kernelend) + goto empty; + s = phys_kernelend; + } + /* Now look whether this region ends within the kernel. */ + if (e > kernload && e <= phys_kernelend) { + if (s >= kernload) { + goto empty; + } + e = kernload; + } + /* Now page align the start and size of the region. */ + s = round_page(s); + e = trunc_page(e); + if (e < s) + e = s; + sz = e - s; + debugf("%08x-%08x = %x\n", s, e, sz); + + /* Check whether some memory is left here. */ + if (sz == 0) { + empty: + printf("skipping\n"); + bcopy(mp + 1, mp, + (cnt - (mp - availmem_regions)) * sizeof(*mp)); + cnt--; + mp--; + continue; + } + + /* Do an insertion sort. */ + for (mp1 = availmem_regions; mp1 < mp; mp1++) + if (s < mp1->mr_start) + break; + if (mp1 < mp) { + bcopy(mp1, mp1 + 1, (char *)mp - (char *)mp1); + mp1->mr_start = s; + mp1->mr_size = sz; + } else { + mp->mr_start = s; + mp->mr_size = sz; + } + } + availmem_regions_sz = cnt; + + /* Fill in phys_avail table, based on availmem_regions */ + debugf("fill in phys_avail:\n"); + for (i = 0, j = 0; i < availmem_regions_sz; i++, j += 2) { + + debugf(" region: 0x%08x - 0x%08x (0x%08x)\n", + availmem_regions[i].mr_start, + availmem_regions[i].mr_start + availmem_regions[i].mr_size, + availmem_regions[i].mr_size); + + phys_avail[j] = availmem_regions[i].mr_start; + phys_avail[j + 1] = availmem_regions[i].mr_start + + availmem_regions[i].mr_size; + } + phys_avail[j] = 0; + phys_avail[j + 1] = 0; +} + +#define TEGRA2_CLK_RST_PA_BASE 0x60006000 + +#define TEGRA2_CLK_RST_OSC_FREQ_DET_REG 0x58 +#define TEGRA2_CLK_RST_OSC_FREQ_DET_STAT_REG 0x5C +#define OSC_FREQ_DET_TRIG (1<<31) +#define OSC_FREQ_DET_BUSY (1<<31) + +static int +tegra2_osc_freq_detect(void) +{ + bus_space_handle_t bsh; + uint32_t c; + uint32_t r=0; + int i=0; + + struct { + uint32_t val; + uint32_t freq; + } freq_det_cnts[] = { + { 732, 12000000 }, + { 794, 13000000 }, + {1172, 19200000 }, + {1587, 26000000 }, + { -1, 0 }, + }; + + printf("Measuring...\n"); + bus_space_map(fdtbus_bs_tag,TEGRA2_CLK_RST_PA_BASE, 0x1000, 0, &bsh); + + bus_space_write_4(fdtbus_bs_tag, bsh, TEGRA2_CLK_RST_OSC_FREQ_DET_REG, + OSC_FREQ_DET_TRIG | 1 ); + do {} while (bus_space_read_4(fdtbus_bs_tag, bsh, + TEGRA2_CLK_RST_OSC_FREQ_DET_STAT_REG) & OSC_FREQ_DET_BUSY); + + c = bus_space_read_4(fdtbus_bs_tag, bsh, TEGRA2_CLK_RST_OSC_FREQ_DET_STAT_REG); + + while (freq_det_cnts[i].val > 0) { + if (((freq_det_cnts[i].val - 3) < c) && (c < (freq_det_cnts[i].val + 3))) + r = freq_det_cnts[i].freq; + i++; + } + printf("c=%u r=%u\n",c,r ); + bus_space_free(fdtbus_bs_tag, bsh, 0x1000); + return r; +} + +void * +initarm(void *mdp, void *unused __unused) +{ + vm_offset_t freemempos; + vm_offset_t dtbp; + vm_offset_t lastaddr; + vm_offset_t l2_start; + struct pv_addr dpcpu; + uint32_t memsize = 0; + u_int l1pagetable; + uint32_t l2size; + int i = 0; + int j = 0; + void *kmdp; + + lastaddr = 0; + dtbp = (vm_offset_t)NULL; + + /* FIXME */ + early_print_init(); + +#define PHYS2VIRT(x) ((x - KERNPHYSADDR) + KERNVIRTADDR) +#define VIRT2PHYS(x) ((x - KERNVIRTADDR) + KERNPHYSADDR) + +#define VALLOC_PAGES(var, np) \ + ALLOC_PAGES((var).pv_pa, (np)); \ + (var).pv_va = PHYS2VIRT((var).pv_pa); + +#define ALLOC_PAGES(var, np) \ + (var) = freemempos; \ + freemempos += (np * PAGE_SIZE); \ + memset((char *)(var), 0, ((np) * PAGE_SIZE)); + +#define ROUND_L_PAGE(x) (((x) + L2_L_OFFSET) & L2_L_FRAME) + + set_cpufuncs(); + + /* + * Mask metadata pointer: it is supposed to be on page boundary. If + * the first argument (mdp) doesn't point to a valid address the + * bootloader must have passed us something else than the metadata + * ptr... In this case we want to fall back to some built-in settings. + */ + mdp = (void *)((uint32_t)mdp & ~PAGE_MASK); + + /* Parse metadata and fetch parameters */ + if (mdp != NULL) { + preload_metadata = mdp; + kmdp = preload_search_by_type("elf kernel"); + if (kmdp != NULL) { + boothowto = MD_FETCH(kmdp, MODINFOMD_HOWTO, int); + kern_envp = MD_FETCH(kmdp, MODINFOMD_ENVP, char *); + dtbp = MD_FETCH(kmdp, MODINFOMD_DTBP, vm_offset_t); + lastaddr = MD_FETCH(kmdp, MODINFOMD_KERNEND, + vm_offset_t); +#ifdef DDB + ksym_start = MD_FETCH(kmdp, MODINFOMD_SSYM, uintptr_t); + ksym_end = MD_FETCH(kmdp, MODINFOMD_ESYM, uintptr_t); +#endif + } + + preload_addr_relocate = KERNVIRTADDR - KERNPHYSADDR; + } else { + /* Fall back to hardcoded metadata. */ + lastaddr = fake_preload_metadata(); + } + +#if defined(FDT_DTB_STATIC) + /* + * In case the device tree blob was not retrieved (from metadata) try + * to use the statically embedded one. + */ + if (dtbp == (vm_offset_t)NULL) + dtbp = (vm_offset_t)&fdt_static_dtb; +#endif + + if (OF_install(OFW_FDT, 0) == FALSE) + while (1); + + if (OF_init((void *)dtbp) != 0) + while (1); + + /* Grab physical memory regions information from device tree. */ + if (fdt_get_mem_regions(availmem_regions, &availmem_regions_sz, + &memsize) != 0) + while(1); + + if (fdt_immr_addr(TEGRA2_BASE) != 0) /* FIXME ???? */ + while (1); + + pmap_bootstrap_lastaddr = fdt_immr_va - ARM_NOCACHE_KVA_SIZE; + + pcpu0_init(); + + /* Calculate number of L2 tables needed for mapping vm_page_array */ + l2size = (memsize / PAGE_SIZE) * sizeof(struct vm_page); + l2size = (l2size >> L1_S_SHIFT) + 1; + + /* + * Add one table for end of kernel map, one for stacks, msgbuf and + * L1 and L2 tables map and one for vectors map and make it div by 4. + */ + l2size += 3; + l2size = (l2size + 3) & ~3; + + freemempos = VIRT2PHYS(ROUND_L_PAGE(lastaddr)); + + VALLOC_PAGES(kernel_l1pt, L1_TABLE_SIZE / PAGE_SIZE); + + for (i = 0; i < l2size; ++i) { + if (!(i % (PAGE_SIZE / L2_TABLE_SIZE_REAL))) { + VALLOC_PAGES(kernel_pt_table[i], + L2_TABLE_SIZE / PAGE_SIZE); + j = i; + } else { + kernel_pt_table[i].pv_va = kernel_pt_table[j].pv_va + + L2_TABLE_SIZE_REAL * (i - j); + kernel_pt_table[i].pv_pa = + kernel_pt_table[i].pv_va - KERNVIRTADDR + + KERNPHYSADDR; + + } + } + /* + * Allocate a page for the system page mapped to 0x00000000 + * or 0xffff0000. This page will just contain the system vectors + * and can be shared by all processes. + */ + + VALLOC_PAGES(systempage, 1); + EPRINTF("systempage PA:0x%08x VA:0x%08x\n", systempage.pv_pa, systempage.pv_va); + + /* Allocate dynamic per-cpu area. */ + VALLOC_PAGES(dpcpu, DPCPU_SIZE / PAGE_SIZE); + dpcpu_init((void *)dpcpu.pv_va, 0); + + /* Allocate stacks for all modes */ + VALLOC_PAGES(fiqstack, FIQ_STACK_SIZE); + VALLOC_PAGES(irqstack, IRQ_STACK_SIZE); + VALLOC_PAGES(abtstack, ABT_STACK_SIZE); + VALLOC_PAGES(undstack, UND_STACK_SIZE); + VALLOC_PAGES(kernelstack, KSTACK_PAGES); + + init_param1(); + + VALLOC_PAGES(msgbufpv, round_page(msgbufsize) / PAGE_SIZE); + + /* + * Now we start construction of the L1 page table + * We start by mapping the L2 page tables into the L1. + * This means that we can replace L1 mappings later on if necessary + */ + l1pagetable = kernel_l1pt.pv_va; + + /* + * Try to map as much as possible of kernel text and data using + * 1MB section mapping and for the rest of initial kernel address + * space use L2 coarse tables. + * + * Link L2 tables for mapping remainder of kernel (modulo 1MB) + * and kernel structures + */ + l2_start = lastaddr & ~(L1_S_OFFSET); + for (i = 0 ; i < l2size - 1; i++) + pmap_link_l2pt(l1pagetable, l2_start + i * L1_S_SIZE, + &kernel_pt_table[i]); + + pmap_curmaxkvaddr = l2_start + (l2size - 1) * L1_S_SIZE; + + /* Map kernel code and data */ + pmap_map_chunk(l1pagetable, KERNVIRTADDR, KERNPHYSADDR, + (((uint32_t)(lastaddr) - KERNVIRTADDR) + PAGE_MASK) & ~PAGE_MASK, + VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); + + /* Map L1 directory and allocated L2 page tables */ + pmap_map_chunk(l1pagetable, kernel_l1pt.pv_va, kernel_l1pt.pv_pa, + L1_TABLE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_PAGETABLE); + + pmap_map_chunk(l1pagetable, kernel_pt_table[0].pv_va, + kernel_pt_table[0].pv_pa, + L2_TABLE_SIZE_REAL * l2size, + VM_PROT_READ|VM_PROT_WRITE, PTE_PAGETABLE); + + /* Map allocated DPCPU, stacks and msgbuf */ + pmap_map_chunk(l1pagetable, dpcpu.pv_va, dpcpu.pv_pa, + PHYS2VIRT(freemempos) - dpcpu.pv_va, + VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); + + /* Link and map the vector page */ + pmap_link_l2pt(l1pagetable, ARM_VECTORS_HIGH, + &kernel_pt_table[l2size - 1]); + pmap_map_entry(l1pagetable, ARM_VECTORS_HIGH, systempage.pv_pa, + VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE, PTE_CACHE); + + /* Map pmap_devmap[] entries */ + if (platform_devmap_init() != 0) + while (1); + pmap_devmap_bootstrap(l1pagetable, pmap_devmap_bootstrap_table); + + /* Switch L1 table */ + cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT); + setttb(kernel_l1pt.pv_pa); + cpu_tlb_flushID(); + cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2))); + + OF_interpret("perform-fixup", 0); + + cninit(); + physmem = memsize / PAGE_SIZE; + + debugf("initarm: console initialized\n"); + debugf(" arg1 mdp = 0x%08x\n", (uint32_t)mdp); + debugf(" boothowto = 0x%08x\n", boothowto); + printf(" dtbp = 0x%08x\n", (uint32_t)dtbp); + print_kernel_section_addr(); + print_kenv(); + + /* + * Pages were allocated during the secondary bootstrap for the + * stacks for different CPU modes. + * We must now set the r13 registers in the different CPU modes to + * point to these stacks. + * Since the ARM stacks use STMFD etc. we must set r13 to the top end + * of the stack memory. + */ + cpu_control(CPU_CONTROL_MMU_ENABLE, CPU_CONTROL_MMU_ENABLE); + set_stackptr(PSR_FIQ32_MODE, + fiqstack.pv_va + FIQ_STACK_SIZE * PAGE_SIZE); + set_stackptr(PSR_IRQ32_MODE, + irqstack.pv_va + IRQ_STACK_SIZE * PAGE_SIZE); + set_stackptr(PSR_ABT32_MODE, + abtstack.pv_va + ABT_STACK_SIZE * PAGE_SIZE); + set_stackptr(PSR_UND32_MODE, + undstack.pv_va + UND_STACK_SIZE * PAGE_SIZE); + + /* + * We must now clean the cache again.... + * Cleaning may be done by reading new data to displace any + * dirty data in the cache. This will have happened in setttb() + * but since we are boot strapping the addresses used for the read + * may have just been remapped and thus the cache could be out + * of sync. A re-clean after the switch will cure this. + * After booting there are no gross relocations of the kernel thus + * this problem will not occur after initarm(). + */ + cpu_idcache_wbinv_all(); + + /* Set stack for exception handlers */ + data_abort_handler_address = (u_int)data_abort_handler; + prefetch_abort_handler_address = (u_int)prefetch_abort_handler; + undefined_handler_address = (u_int)undefinedinstruction_bounce; + undefined_init(); + + init_proc0(kernelstack.pv_va); + arm_vector_init(ARM_VECTORS_HIGH, ARM_VEC_ALL); + + dump_avail[0] = 0; + dump_avail[1] = memsize; + dump_avail[2] = 0; + dump_avail[3] = 0; + + pmap_bootstrap(PHYS2VIRT(freemempos), pmap_bootstrap_lastaddr, &kernel_l1pt); + msgbufp = (void *)msgbufpv.pv_va; + msgbufinit(msgbufp, msgbufsize); + mutex_init(); + + /* + * Prepare map of physical memory regions available to vm subsystem. + */ + + physmap_init(); + + /* Do basic tuning, hz etc */ + init_param2(physmem); + kdb_init(); + return ((void *)(kernelstack.pv_va + USPACE_SVC_STACK_TOP - + sizeof(struct pcb))); +} + +#define FDT_DEVMAP_MAX (1 + 2 + 1 + 1) /* FIXME */ +static struct pmap_devmap fdt_devmap[FDT_DEVMAP_MAX] = { + { 0, 0, 0, 0, 0, } +}; + +/* + * Construct pmap_devmap[] with DT-derived config data. + */ +static int +platform_devmap_init(void) +{ + int i = 0; + fdt_devmap[i].pd_va = 0xe0000000; + fdt_devmap[i].pd_pa = 0x70000000; + fdt_devmap[i].pd_size = 0x100000; + fdt_devmap[i].pd_prot = VM_PROT_READ | VM_PROT_WRITE; + fdt_devmap[i].pd_cache = PTE_NOCACHE; + i++; + + pmap_devmap_bootstrap_table = &fdt_devmap[0]; + return (0); +} + + +struct arm32_dma_range * +bus_dma_get_range(void) +{ + + return (NULL); +} + +int +bus_dma_get_range_nb(void) +{ + + return (0); +} Added: head/sys/boot/fdt/dts/trimslice.dts ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/boot/fdt/dts/trimslice.dts Wed Aug 15 06:06:43 2012 (r239280) @@ -0,0 +1,143 @@ +/*- + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * + * Developed by Damjan Marion <damjan.mar...@gmail.com> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. *** DIFF OUTPUT TRUNCATED AT 1000 LINES *** _______________________________________________ svn-src-head@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-head To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"