Index: sys/dev/fdt/fdt_regions.h =================================================================== --- sys/dev/fdt/fdt_regions.h (revision 0) +++ sys/dev/fdt/fdt_regions.h (working copy) @@ -0,0 +1,172 @@ +/*- + * Copyright (c) 2013 Aleksandr Rybalko + * 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. + * + * $FreeBSD$ + */ + +#ifndef _DEV_FDT_FDT_REGIONS_H_ +#define _DEV_FDT_FDT_REGIONS_H_ + +#define REGION_ALIGN(r, sz) \ +do { \ + vm_offset_t tmp, mask; \ + mask = ((vm_offset_t)sz - 1); \ + tmp = (r).mr_start & mask; \ + (r).mr_start &= ~mask; \ + (r).mr_size += (tmp + mask); \ + (r).mr_size &= ~mask; \ +} while (0) + +#define REGION_BEGIN(r) ((r).mr_start) +#define REGION_END(r) ((r).mr_start + (r).mr_size) +#define POINT_IN_REGION(r, p) ((REGION_BEGIN(r) <= (p)) && \ + ((p) <= REGION_END(r))) +#define REGIONS_BISECTS(r1, r2) (POINT_IN_REGION(r1, REGION_BEGIN(r2)) || \ + POINT_IN_REGION(r1, REGION_END(r2))) +#define REGION_COPY(dst, src) do {(dst).mr_start = (src).mr_start; \ + (dst).mr_size = (src).mr_size;} while (0) + +#define REGION_SWAP(dst, src) \ +do { \ + struct mem_region tmp; \ + REGION_COPY(tmp, dst); \ + REGION_COPY(dst, src); \ + REGION_COPY(src, tmp); \ +} while (0) + +static inline void +bubble_sort(vm_offset_t *ar, int cnt) +{ + int i, swapped; + vm_offset_t tmp; + + for (;;) { + for (i = 0, swapped = 0; i < (cnt - 1); i ++) { + if (ar[i + 1] < ar[i]) { + tmp = ar[i + 1]; + ar[i + 1] = ar[i]; + ar[i] = tmp; + swapped++; + } + } + if (!swapped) + break; + } +} + +static inline void +regions_sort(struct mem_region *r, int cnt) +{ + int i, swapped; + + if (cnt < 2) /* Nothing to sort. */ + return; + + for (;;) { + for (i = 0, swapped = 0; i < (cnt - 1); i ++) { + if (r[i + 1].mr_start < r[i].mr_start) { + REGION_SWAP(r[i], r[i + 1]); + swapped++; + } + } + if (!swapped) + break; + } +} + +static inline void +range_diff(struct mem_region *r1, struct mem_region *r2, struct mem_region *ret) +{ + vm_offset_t ar[4]; + int i = 0; + + bzero(ret, sizeof(struct mem_region) * 2); + ar[0] = REGION_BEGIN(*r1); + ar[1] = REGION_END(*r1); + ar[2] = REGION_BEGIN(*r2); + ar[3] = REGION_END(*r2); + + bubble_sort(ar, 4); + + if (ar[0] == REGION_BEGIN(*r1)) { + ret[i].mr_start = ar[0]; + ret[i].mr_size = ar[1] - ar[0]; + i++; + } + if (ar[3] == REGION_END(*r1)) { + ret[i].mr_start = ar[2]; + ret[i].mr_size = ar[3] - ar[2]; + } +} + +static inline void +ranges_diff(struct mem_region *main, int *ms, struct mem_region *sub, int ss) +{ + struct mem_region ret[2]; + int m, r; + + for (r = 0; r < ss; r++) { + for (m = 0; m < *ms; m++) { + range_diff(&main[m], &sub[r], ret); + REGION_COPY(main[m], ret[0]); + if (ret[1].mr_size != 0) { + REGION_COPY(main[*ms], ret[1]); + (*ms)++; + regions_sort(main, *ms); + } + } + } +} + +static inline void +ranges_join(struct mem_region *main, int *ms) +{ + int m, result_sz; + + if (*ms < 2) /* Nothing to join. */ + return; + result_sz = *ms; + for (m = 0; m < (*ms - 1); m++) { + if (REGION_END(main[m]) == REGION_BEGIN(main[m + 1])) { + main[m].mr_size += main[m + 1].mr_size; + main[m + 1].mr_start = UINT_MAX; + main[m + 1].mr_size = 0; + result_sz--; + } + } + regions_sort(main, *ms); + *ms = result_sz; +} + +static inline void +ranges_align(struct mem_region *main, int cnt, vm_offset_t sz) +{ + int m; + + for (m = 0; m < cnt; m++) + REGION_ALIGN(main[m], sz); +} + +#endif /* _DEV_FDT_FDT_REGIONS_H_ */ Property changes on: sys/dev/fdt/fdt_regions.h ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: sys/boot/fdt/dts/efikamx.dts =================================================================== --- sys/boot/fdt/dts/efikamx.dts (revision 258091) +++ sys/boot/fdt/dts/efikamx.dts (working copy) @@ -34,9 +34,12 @@ /dts-v1/; /include/ "imx51x.dtsi" +/memreserve/ 0xaef00000 0x00400000; + / { model = "Genesi Efika MX"; compatible = "genesi,imx51-efikamx"; + memreserve = <0xaef00000 0x00400000>; memory { /* RAM 512M */ @@ -44,7 +47,14 @@ }; localbus@5e000000 { - ipu3@5e000000 { + display: ipu3@5e000000 { + device_type = "display"; + /* Have to be filled by u-boot. */ + address = <0xaef76c60>; + depth = <24>; + width = <1280>; + height = <720>; + linebytes = <3840>; status = "okay"; }; }; @@ -89,6 +99,18 @@ gpio@73f90000 { status = "okay"; }; + usbotg: usb@73f80000 { + status = "okay"; + }; + usbh1: usb@73f80200 { + status = "okay"; + }; + usbh2: usb@73f80400 { + status = "okay"; + }; + usbh3: usb@73f80600 { + status = "okay"; + }; wdog@73f98000 { status = "okay"; }; @@ -112,6 +134,7 @@ aliases { UART1 = &UART1; SSI2 = &SSI2; + screen = &display; }; chosen { Index: sys/arm/arm/machdep.c =================================================================== --- sys/arm/arm/machdep.c (revision 258091) +++ sys/arm/arm/machdep.c (working copy) @@ -65,6 +65,7 @@ #include #include #include +#include #include #include #include @@ -104,6 +105,7 @@ #ifdef FDT #include +#include #include #endif @@ -1188,8 +1190,8 @@ void * initarm(struct arm_boot_params *abp) { + struct mem_region *availmem_regions; struct mem_region memory_regions[FDT_MEM_REGIONS]; - struct mem_region availmem_regions[FDT_MEM_REGIONS]; struct mem_region reserved_regions[FDT_MEM_REGIONS]; struct pv_addr kernel_l1pt; struct pv_addr dpcpu; @@ -1202,9 +1204,6 @@ int memory_regions_sz; int availmem_regions_sz; int reserved_regions_sz; - vm_offset_t start, end; - vm_offset_t rstart, rend; - int curr; lastaddr = parse_boot_param(abp); memsize = 0; @@ -1242,66 +1241,24 @@ /* Grab physical memory regions information from device tree. */ if (fdt_get_reserved_regions(reserved_regions, &reserved_regions_sz) != 0) reserved_regions_sz = 0; - + /* - * Now exclude all the reserved regions + * Extend the reserved regions, to PAGE_SIZE. */ - curr = 0; - for (i = 0; i < memory_regions_sz; i++) { - start = memory_regions[i].mr_start; - end = start + memory_regions[i].mr_size; - for (j = 0; j < reserved_regions_sz; j++) { - rstart = reserved_regions[j].mr_start; - rend = rstart + reserved_regions[j].mr_size; - /* - * Restricted region is before available - * Skip restricted region - */ - if (rend <= start) - continue; - /* - * Restricted region is behind available - * No further processing required - */ - if (rstart >= end) - break; - /* - * Restricted region includes memory region - * skip available region - */ - if ((start >= rstart) && (rend >= end)) { - start = rend; - end = rend; - break; - } - /* - * Memory region includes restricted region - */ - if ((rstart > start) && (end > rend)) { - availmem_regions[curr].mr_start = start; - availmem_regions[curr++].mr_size = rstart - start; - start = rend; - break; - } - /* - * Memory region partially overlaps with restricted - */ - if ((rstart >= start) && (rstart <= end)) { - end = rstart; - } - else if ((rend >= start) && (rend <= end)) { - start = rend; - } - } + ranges_align(reserved_regions, reserved_regions_sz, PAGE_SIZE); + /* + * Now exclude all the reserved regions. + */ + ranges_diff(memory_regions, &memory_regions_sz, reserved_regions, + reserved_regions_sz); + /* + * Join neighbor regions. + */ + ranges_join(memory_regions, &memory_regions_sz); - if (end > start) { - availmem_regions[curr].mr_start = start; - availmem_regions[curr++].mr_size = end - start; - } - } + availmem_regions = memory_regions; + availmem_regions_sz = memory_regions_sz; - availmem_regions_sz = curr; - /* Platform-specific initialisation */ initarm_early_init(); @@ -1506,6 +1463,8 @@ init_param2(physmem); kdb_init(); +#define DUMP_REGION(r) printf("0x%08tx+0x%08zx", (r).mr_start, (r).mr_size) + return ((void *)(kernelstack.pv_va + USPACE_SVC_STACK_TOP - sizeof(struct pcb))); } Index: sys/arm/conf/EFIKA_MX =================================================================== --- sys/arm/conf/EFIKA_MX (revision 258091) +++ sys/arm/conf/EFIKA_MX (working copy) @@ -169,6 +169,8 @@ # NOTE: serial console will be disabled if syscons enabled # Uncomment following lines for framebuffer/syscons support device vt +options VT_FB_DEFAULT_WIDTH=1280 +options VT_FB_DEFAULT_HEIGHT=720 device vkbd device kbdmux device ukbd # Allow keyboard like HIDs to control console Index: sys/arm/freescale/imx/imx51_machdep.c =================================================================== --- sys/arm/freescale/imx/imx51_machdep.c (revision 258091) +++ sys/arm/freescale/imx/imx51_machdep.c (working copy) @@ -36,10 +36,15 @@ #include +#include #include #include #include +#include +#include +#include + #include vm_offset_t @@ -62,6 +67,9 @@ initarm_gpio_init(void) { + cpufunc_control(CPU_CONTROL_DC_ENABLE|CPU_CONTROL_IC_ENABLE, + CPU_CONTROL_DC_ENABLE|CPU_CONTROL_IC_ENABLE); + } void @@ -77,14 +85,47 @@ * * Notably missing are entries for GPU, IPU, in general anything video related. */ + +int fb_base_global = 0, fb_size_global = 0; + int initarm_devmap_init(void) { + uint32_t address, height, linebytes, size; + phandle_t node; + char type[64]; arm_devmap_add_entry(0x70000000, 0x00100000); arm_devmap_add_entry(0x73f00000, 0x00100000); arm_devmap_add_entry(0x83f00000, 0x00100000); +// arm_devmap_add_entry(0xaef00000/* 0xaef76c50 */, 0x00400000); + node = OF_finddevice("screen"); + OF_getprop(node, "device_type", type, sizeof(type)); + if (strcmp(type, "display") != 0) + return (0); + +#define GET(name, var) \ + if (OF_getproplen(node, (name)) != sizeof(var)) \ + return (0); \ + OF_getencprop(node, (name), &var, sizeof(var)); \ + if (var == 0) \ + return (0); + + GET("height", height) + GET("linebytes", linebytes) + GET("address", address) +#undef GET + + size = height * linebytes; + size = roundup(address + size, L1_S_SIZE); + + address = rounddown(address, L1_S_SIZE); + size -= address; + fb_base_global = address; + fb_size_global = size; + arm_devmap_add_entry(address, size); + return (0); }