boot/platform/u-boot: Drop ARM support.
Newer versions of u-boot support EFI natively, which is what we have been making use of instead. There may be some use for the "native" u-boot loader still on PowerPC, but otherwise the EFI support is much more advanced and even in u-boot supports as or more features than "native" loaders, so there is no reason to keep this around.
This commit is contained in:
@@ -1,80 +0,0 @@
|
|||||||
# BeagleBoard board-specific definitions
|
|
||||||
|
|
||||||
HAIKU_BOARD_DESCRIPTION = "BeagleBoard" ;
|
|
||||||
HAIKU_BOARD_FDT_NAME = "omap3-beagle-xm" ;
|
|
||||||
|
|
||||||
|
|
||||||
#
|
|
||||||
# Various hardcoded addresses
|
|
||||||
#
|
|
||||||
|
|
||||||
# load address for haiku_loader
|
|
||||||
HAIKU_BOARD_LOADER_BASE = 0x80800000 ;
|
|
||||||
# entry points (raw binary, and netbsd loader emulation)
|
|
||||||
HAIKU_BOARD_LOADER_ENTRY_RAW = $(HAIKU_BOARD_LOADER_BASE) ;
|
|
||||||
HAIKU_BOARD_LOADER_ENTRY_NBSD = `printf \"obase=16;ibase=16;8 + %x\\n\" $(HAIKU_BOARD_LOADER_BASE)|bc` ;
|
|
||||||
HAIKU_BOARD_LOADER_ENTRY_LINUX = `printf \"obase=16;ibase=16;10 + %x\\n\" $(HAIKU_BOARD_LOADER_BASE)|bc` ;
|
|
||||||
|
|
||||||
HAIKU_BOARD_LOADER_ENTRY = $(HAIKU_BOARD_LOADER_ENTRY_NBSD) ;
|
|
||||||
HAIKU_BOARD_LOADER_FAKE_OS = netbsd ;
|
|
||||||
|
|
||||||
# load address for haiku_loader uimage
|
|
||||||
# (must be different than real load address)
|
|
||||||
HAIKU_BOARD_LOADER_UIBASE = 0x82800000 ;
|
|
||||||
|
|
||||||
#
|
|
||||||
# Flash image
|
|
||||||
#
|
|
||||||
|
|
||||||
# OMAP x-loader image, must be first file on FAT partition
|
|
||||||
HAIKU_BOARD_MLO_IMAGE ?= MLO ;
|
|
||||||
HAIKU_BOARD_MLO_IMAGE_URL =
|
|
||||||
http://downloads.angstrom-distribution.org/demo/beagleboard/MLO ;
|
|
||||||
|
|
||||||
# u-boot binary image filename, to build the flash image
|
|
||||||
# XXX: Locate it somehow (for now just put it in generated/)
|
|
||||||
HAIKU_BOARD_UBOOT_IMAGE ?= u-boot.img ;
|
|
||||||
HAIKU_BOARD_UBOOT_IMAGE_URL =
|
|
||||||
http://downloads.angstrom-distribution.org/demo/beagleboard/u-boot.img ;
|
|
||||||
|
|
||||||
#
|
|
||||||
# mmc/SD image
|
|
||||||
#
|
|
||||||
|
|
||||||
# in MB
|
|
||||||
HAIKU_BOARD_SDIMAGE_SIZE = 64 ;
|
|
||||||
|
|
||||||
# in MB
|
|
||||||
HAIKU_BOARD_SDIMAGE_FAT_SIZE = 32 ;
|
|
||||||
|
|
||||||
mloFile = [ DownloadFile $(HAIKU_BOARD_MLO_IMAGE)
|
|
||||||
: $(HAIKU_BOARD_MLO_IMAGE_URL) ] ;
|
|
||||||
|
|
||||||
ubootFile = [ DownloadFile $(HAIKU_BOARD_UBOOT_IMAGE)
|
|
||||||
: $(HAIKU_BOARD_UBOOT_IMAGE_URL) ] ;
|
|
||||||
|
|
||||||
# U-Boot environment
|
|
||||||
# We load the uImage 2MB above its final destination, bootm will decode
|
|
||||||
# it to the proper location. Our image is smaller than 2MB so this works.
|
|
||||||
#HAIKU_BOARD_SDIMAGE_UBOOT_UENV_NAME = uEnv.txt ;
|
|
||||||
HAIKU_BOARD_SDIMAGE_UBOOT_UENV = "uenvcmd=run loadImage; run mmcboot; \
|
|
||||||
loadImage=fatload mmc0 0 $(HAIKU_BOARD_LOADER_UIBASE) haiku_loader_linux.ub; fatload mmc 0 0x80100000 /fdt/$(HAIKU_BOARD_FDT_NAME).dtb; fatload mmc 0 0x81200000 haiku-floppyboot.tgz.ub; \
|
|
||||||
mmcboot=bootm $(HAIKU_BOARD_LOADER_UIBASE) 0x81200000 0x80100000" ;
|
|
||||||
|
|
||||||
HAIKU_BOARD_SDIMAGE_FILES =
|
|
||||||
$(mloFile)
|
|
||||||
$(ubootFile)
|
|
||||||
haiku_loader_nbsd.ub
|
|
||||||
haiku_loader_linux.ub
|
|
||||||
haiku-floppyboot.tgz.ub
|
|
||||||
;
|
|
||||||
|
|
||||||
|
|
||||||
#
|
|
||||||
# gcc flags for the specific cpu
|
|
||||||
|
|
||||||
local flags = -mcpu=cortex-a8 -mfpu=vfpv3 -mfloat-abi=hard ;
|
|
||||||
|
|
||||||
HAIKU_ASFLAGS_$(HAIKU_PACKAGING_ARCH) += $(flags) ;
|
|
||||||
HAIKU_CCFLAGS_$(HAIKU_PACKAGING_ARCH) += $(flags) ;
|
|
||||||
HAIKU_C++FLAGS_$(HAIKU_PACKAGING_ARCH) += $(flags) ;
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
# BeagleBone board-specific definitions
|
|
||||||
|
|
||||||
HAIKU_BOARD_DESCRIPTION = "BeagleBone" ;
|
|
||||||
HAIKU_BOARD_FDT_NAME = "boneblack" ;
|
|
||||||
|
|
||||||
# Not that many in the wild
|
|
||||||
#HAIKU_BOARD_FDT_NAME = "beaglebone" ;
|
|
||||||
|
|
||||||
|
|
||||||
#
|
|
||||||
# Various hardcoded addresses
|
|
||||||
#
|
|
||||||
|
|
||||||
# load address for haiku_loader
|
|
||||||
HAIKU_BOARD_LOADER_BASE = 0x80800000 ;
|
|
||||||
HAIKU_BOARD_LOADER_ENTRY_RAW = $(HAIKU_BOARD_LOADER_BASE) ;
|
|
||||||
HAIKU_BOARD_LOADER_ENTRY_NBSD = `printf \"obase=16;ibase=16;8 + %x\\n\" $(HAIKU_BOARD_LOADER_BASE)|bc` ;
|
|
||||||
HAIKU_BOARD_LOADER_ENTRY_LINUX = `printf \"obase=16;ibase=16;10 + %x\\n\" $(HAIKU_BOARD_LOADER_BASE)|bc` ;
|
|
||||||
|
|
||||||
#
|
|
||||||
# mmc/SD image
|
|
||||||
#
|
|
||||||
|
|
||||||
# in MB
|
|
||||||
HAIKU_BOARD_SDIMAGE_SIZE = 64 ;
|
|
||||||
HAIKU_BOARD_SDIMAGE_FAT_SIZE = 32 ;
|
|
||||||
|
|
||||||
# OMAP x-loader image, must be first file on FAT partition
|
|
||||||
HAIKU_BOARD_MLO_IMAGE_URL = https://github.com/haiku/firmware/raw/master/arm/beaglebone ;
|
|
||||||
mloFile = [ DownloadFile MLO : $(HAIKU_BOARD_MLO_IMAGE_URL)/MLO ] ;
|
|
||||||
|
|
||||||
# u-boot image
|
|
||||||
HAIKU_BOARD_UBOOT_IMAGE_URL = https://github.com/haiku/firmware/raw/master/arm/beaglebone ;
|
|
||||||
ubootFile = [ DownloadFile u-boot.img : $(HAIKU_BOARD_UBOOT_IMAGE_URL)/u-boot.img ] ;
|
|
||||||
|
|
||||||
# U-Boot environment
|
|
||||||
HAIKU_BOARD_SDIMAGE_UBOOT_SCRIPT_NAME = boot.scr ;
|
|
||||||
HAIKU_BOARD_SDIMAGE_UBOOT_SCRIPT = "\
|
|
||||||
fatload mmc 0 ${fdt_addr_r} /fdt/$(HAIKU_BOARD_FDT_NAME).dtb \
|
|
||||||
fdt addr ${fdt_addr_r} \
|
|
||||||
fatload mmc 0 ${ramdisk_addr_r} haiku-floppyboot.tgz.ub \
|
|
||||||
fatload mmc 0 ${kernel_addr_r} haiku_loader_linux.ub \
|
|
||||||
bootm ${kernel_addr_r} ${ramdisk_addr_r} ${fdt_addr_r}" ;
|
|
||||||
|
|
||||||
HAIKU_BOARD_SDIMAGE_FILES =
|
|
||||||
$(mloFile)
|
|
||||||
$(ubootFile)
|
|
||||||
haiku_loader_linux.ub
|
|
||||||
haiku-floppyboot.tgz.ub
|
|
||||||
$(HAIKU_BOARD_SDIMAGE_UBOOT_SCRIPT_NAME)
|
|
||||||
;
|
|
||||||
|
|
||||||
#
|
|
||||||
# gcc flags for the specific cpu
|
|
||||||
|
|
||||||
local flags = -mcpu=cortex-a8 -mfpu=vfpv3 -mfloat-abi=hard ;
|
|
||||||
|
|
||||||
HAIKU_ASFLAGS_$(HAIKU_PACKAGING_ARCH) += $(flags) ;
|
|
||||||
HAIKU_CCFLAGS_$(HAIKU_PACKAGING_ARCH) += $(flags) ;
|
|
||||||
HAIKU_C++FLAGS_$(HAIKU_PACKAGING_ARCH) += $(flags) ;
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
# Cubieboard 4 board-specific definitions
|
|
||||||
# This likely could be easily used for other Allwinner chipsets
|
|
||||||
|
|
||||||
HAIKU_BOARD_DESCRIPTION = "Cubieboard 4 (CC-A80)" ;
|
|
||||||
HAIKU_BOARD_FDT_NAME = "cubieboard4" ;
|
|
||||||
|
|
||||||
#
|
|
||||||
# Various hardcoded addresses
|
|
||||||
#
|
|
||||||
|
|
||||||
# 0x20000000 = SDRAM start
|
|
||||||
# 0x20007800 = haiku_loader_linux.ub
|
|
||||||
# 0x20087800 = BASE
|
|
||||||
|
|
||||||
HAIKU_BOARD_LOADER_BASE = 0x20087800 ;
|
|
||||||
HAIKU_BOARD_LOADER_ENTRY_RAW = $(HAIKU_BOARD_LOADER_BASE) ;
|
|
||||||
HAIKU_BOARD_LOADER_ENTRY_NBSD = `printf \"obase=16;ibase=16;8 + %x\\n\" $(HAIKU_BOARD_LOADER_BASE)|bc` ;
|
|
||||||
HAIKU_BOARD_LOADER_ENTRY_LINUX = `printf \"obase=16;ibase=16;10 + %x\\n\" $(HAIKU_BOARD_LOADER_BASE)|bc` ;
|
|
||||||
|
|
||||||
#
|
|
||||||
# mmc/SD image
|
|
||||||
#
|
|
||||||
|
|
||||||
HAIKU_BOARD_FIRMWARE_URL = "https://github.com/cubieboard/CC-A80-binaries/raw/master/bin" ;
|
|
||||||
|
|
||||||
# u-boot image
|
|
||||||
# Dear Cubbieboard, add fdt_addr_r, ramdisk_addr_r, kernel_addr_r to u-boot
|
|
||||||
HAIKU_BOARD_SDIMAGE_UBOOT_SCRIPT_NAME = boot.scr ;
|
|
||||||
HAIKU_BOARD_SDIMAGE_UBOOT_SCRIPT = "\
|
|
||||||
fatload mmc 0 0x20800000 haiku-floppyboot.tgz.ub \
|
|
||||||
fatload mmc 0 0x20007800 haiku_loader_linux.ub \
|
|
||||||
bootm 0x20007800 0x20800000" ;
|
|
||||||
|
|
||||||
HAIKU_BOARD_SDIMAGE_FAT_SIZE = 32 ;
|
|
||||||
HAIKU_BOARD_SDIMAGE_FILES =
|
|
||||||
haiku_loader_linux.ub
|
|
||||||
haiku-floppyboot.tgz.ub
|
|
||||||
$(HAIKU_BOARD_SDIMAGE_UBOOT_SCRIPT_NAME)
|
|
||||||
;
|
|
||||||
|
|
||||||
HAIKU_BOARD_SDIMAGE_BEGIN = 40950 ; # 512-byte sectors (divisible by 63)
|
|
||||||
HAIKU_BOARD_SDIMAGE_SIZE = 128 ; # MiB
|
|
||||||
|
|
||||||
boot0File = [ DownloadFile sdcard-boot0 : $(HAIKU_BOARD_FIRMWARE_URL)/sdcard-boot0 ] ;
|
|
||||||
boot1File = [ DownloadFile sdcard-boot1 : $(HAIKU_BOARD_FIRMWARE_URL)/sdcard-boot1 ] ;
|
|
||||||
|
|
||||||
# The Allwinner chips require an SD card "blessed" with
|
|
||||||
# the boot0 SPL and boot1 (u-boot) at a fixed location on
|
|
||||||
# the SD card. (Dear AW, please support loading from FAT)
|
|
||||||
HAIKU_BOARD_SDIMAGE_BOOT0_FILE = $(boot0File) ;
|
|
||||||
HAIKU_BOARD_SDIMAGE_BOOT0_SEEK = 8192 ;
|
|
||||||
HAIKU_BOARD_SDIMAGE_BOOT1_FILE = $(boot1File) ;
|
|
||||||
HAIKU_BOARD_SDIMAGE_BOOT1_SEEK = 19554304 ;
|
|
||||||
|
|
||||||
#
|
|
||||||
# gcc flags for the specific cpu
|
|
||||||
#
|
|
||||||
|
|
||||||
local flags = -march=armv7-a -mfpu=vfpv3-d16 -mfloat-abi=hard ;
|
|
||||||
|
|
||||||
HAIKU_ASFLAGS_$(HAIKU_PACKAGING_ARCH) += $(flags) ;
|
|
||||||
HAIKU_CCFLAGS_$(HAIKU_PACKAGING_ARCH) += $(flags) ;
|
|
||||||
HAIKU_C++FLAGS_$(HAIKU_PACKAGING_ARCH) += $(flags) ;
|
|
||||||
|
|
||||||
# Workaround for ld using 32k for alignment despite forcing it in the config...
|
|
||||||
# should definitely not be needed!
|
|
||||||
HAIKU_KERNEL_LINKFLAGS +=
|
|
||||||
-Wl,-z -Wl,max-page-size=0x1000
|
|
||||||
-Wl,-z -Wl,common-page-size=0x1000 ;
|
|
||||||
HAIKU_LINKFLAGS_$(HAIKU_PACKAGING_ARCH) +=
|
|
||||||
-Wl,-z -Wl,max-page-size=0x1000
|
|
||||||
-Wl,-z -Wl,common-page-size=0x1000 ;
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
# Gumstix Verdex board-specific definitions
|
|
||||||
|
|
||||||
HAIKU_BOARD_DESCRIPTION = "Openmoko Neo FreeRunner" ;
|
|
||||||
|
|
||||||
#
|
|
||||||
# Various hardcoded addresses
|
|
||||||
#
|
|
||||||
|
|
||||||
# load address for haiku_loader
|
|
||||||
HAIKU_BOARD_LOADER_BASE = 0x32000000 ;
|
|
||||||
# entry points (raw binary, and netbsd loader emulation)
|
|
||||||
HAIKU_BOARD_LOADER_ENTRY_RAW = 0x32000000 ;
|
|
||||||
HAIKU_BOARD_LOADER_ENTRY_NBSD = 0x32000008 ;
|
|
||||||
|
|
||||||
HAIKU_BOARD_LOADER_ENTRY = $(HAIKU_BOARD_LOADER_ENTRY_NBSD) ;
|
|
||||||
HAIKU_BOARD_LOADER_FAKE_OS = netbsd ;
|
|
||||||
|
|
||||||
# load address for haiku_loader uimage
|
|
||||||
# (must be different than real load address)
|
|
||||||
HAIKU_BOARD_LOADER_UIBASE = 0x34000000 ;
|
|
||||||
|
|
||||||
#
|
|
||||||
# Flash image
|
|
||||||
#
|
|
||||||
|
|
||||||
# u-boot binary image filename, to build the flash image
|
|
||||||
# XXX: Locate it somehow (for now just put it in generated/)
|
|
||||||
#HAIKU_BOARD_UBOOT_IMAGE ?= u-boot-verdex-400-r1604.bin ;
|
|
||||||
#HAIKU_BOARD_UBOOT_IMAGE_URL =
|
|
||||||
# http://www.gumstix.net/feeds/u-boot/u-boot-verdex-400-r1604.bin ;
|
|
||||||
|
|
||||||
|
|
||||||
#
|
|
||||||
# mmc/SD image
|
|
||||||
#
|
|
||||||
|
|
||||||
# in MB
|
|
||||||
HAIKU_BOARD_SDIMAGE_SIZE = 256 ;
|
|
||||||
|
|
||||||
# in MB
|
|
||||||
HAIKU_BOARD_SDIMAGE_FAT_SIZE = 32 ;
|
|
||||||
|
|
||||||
# autoboot script
|
|
||||||
HAIKU_BOARD_SDIMAGE_UBOOT_SCRIPT_NAME = uImage.bin ;
|
|
||||||
|
|
||||||
HAIKU_BOARD_SDIMAGE_UBOOT_SCRIPT = "\
|
|
||||||
if mmcinit; then \
|
|
||||||
neo backlight off; \
|
|
||||||
fatload mmc 0 $(HAIKU_BOARD_LOADER_UIBASE) haiku_loader_nbsd.ub; \
|
|
||||||
neo backlight on; \
|
|
||||||
bootm $(HAIKU_BOARD_LOADER_UIBASE); \
|
|
||||||
fi" ;
|
|
||||||
|
|
||||||
HAIKU_BOARD_SDIMAGE_FILES =
|
|
||||||
haiku_loader
|
|
||||||
haiku_loader.ub
|
|
||||||
haiku_loader_nbsd.ub
|
|
||||||
$(HAIKU_BOARD_SDIMAGE_UBOOT_SCRIPT_NAME)
|
|
||||||
;
|
|
||||||
|
|
||||||
|
|
||||||
#
|
|
||||||
# gcc flags for the specific cpu
|
|
||||||
#
|
|
||||||
|
|
||||||
HAIKU_CCFLAGS_$(HAIKU_PACKAGING_ARCH) += -mcpu=arm920t ;
|
|
||||||
HAIKU_C++FLAGS_$(HAIKU_PACKAGING_ARCH) += -mcpu=arm920t ;
|
|
||||||
|
|
||||||
# Workaround for ld using 32k for alignment despite forcing it in the config...
|
|
||||||
# should definitely not be needed!
|
|
||||||
HAIKU_KERNEL_LINKFLAGS +=
|
|
||||||
-Wl,-z -Wl,max-page-size=0x1000
|
|
||||||
-Wl,-z -Wl,common-page-size=0x1000 ;
|
|
||||||
HAIKU_LINKFLAGS_$(HAIKU_PACKAGING_ARCH) +=
|
|
||||||
-Wl,-z -Wl,max-page-size=0x1000
|
|
||||||
-Wl,-z -Wl,common-page-size=0x1000 ;
|
|
||||||
|
|
||||||
@@ -1,101 +0,0 @@
|
|||||||
# Gumstix Overo board-specific definitions
|
|
||||||
|
|
||||||
HAIKU_BOARD_DESCRIPTION = "Gumstix Overo" ;
|
|
||||||
HAIKU_BOARD_FDT_NAME = "omap3-overo-tobi" ;
|
|
||||||
|
|
||||||
#
|
|
||||||
# Various hardcoded addresses
|
|
||||||
#
|
|
||||||
|
|
||||||
# load address for haiku_loader
|
|
||||||
HAIKU_BOARD_LOADER_BASE = 0x80800000 ;
|
|
||||||
# entry points (raw binary, and netbsd loader emulation)
|
|
||||||
HAIKU_BOARD_LOADER_ENTRY_RAW = 0x80800000 ;
|
|
||||||
HAIKU_BOARD_LOADER_ENTRY_NBSD = 0x80800008 ;
|
|
||||||
HAIKU_BOARD_LOADER_ENTRY_LINUX = 0x80800010 ;
|
|
||||||
|
|
||||||
HAIKU_BOARD_LOADER_ENTRY = $(HAIKU_BOARD_LOADER_ENTRY_NBSD) ;
|
|
||||||
HAIKU_BOARD_LOADER_FAKE_OS = netbsd ;
|
|
||||||
|
|
||||||
# load address for haiku_loader uimage
|
|
||||||
# (must be different than real load address)
|
|
||||||
HAIKU_BOARD_LOADER_UIBASE = 0x82800000 ;
|
|
||||||
|
|
||||||
#
|
|
||||||
# Flash image
|
|
||||||
#
|
|
||||||
|
|
||||||
# cf. http://gumstix.org/how-to/70-writing-images-to-flash.html
|
|
||||||
|
|
||||||
# OMAP x-loader image, must be first file in Flash image
|
|
||||||
HAIKU_BOARD_MLO_IMAGE ?= MLO ;
|
|
||||||
HAIKU_BOARD_MLO_IMAGE_URL =
|
|
||||||
http://cumulus.gumstix.org/images/angstrom/developer/current/MLO ;
|
|
||||||
|
|
||||||
# u-boot binary image filename, to build the flash image
|
|
||||||
# XXX: Locate it somehow (for now just put it in generated/)
|
|
||||||
HAIKU_BOARD_UBOOT_IMAGE ?= u-boot.bin ;
|
|
||||||
HAIKU_BOARD_UBOOT_IMAGE_URL =
|
|
||||||
http://cumulus.gumstix.org/images/angstrom/developer/current/u-boot.bin ;
|
|
||||||
|
|
||||||
mloFile = [ DownloadFile $(HAIKU_BOARD_MLO_IMAGE)
|
|
||||||
: $(HAIKU_BOARD_MLO_IMAGE_URL) ] ;
|
|
||||||
|
|
||||||
ubootFile = [ DownloadFile $(HAIKU_BOARD_UBOOT_IMAGE)
|
|
||||||
: $(HAIKU_BOARD_UBOOT_IMAGE_URL) ] ;
|
|
||||||
|
|
||||||
FLASH_IMAGE_PARTS =
|
|
||||||
$(mloFile)
|
|
||||||
$(ubootFile)
|
|
||||||
;
|
|
||||||
|
|
||||||
# flash offsets:
|
|
||||||
# in kB
|
|
||||||
FLASH_IMAGE_LOADER_OFFSET = 31744 ;
|
|
||||||
|
|
||||||
FLASH_OFFSET on $(mloFile) = 0 ;
|
|
||||||
FLASH_OFFSET on $(ubootFile) = 512 ;
|
|
||||||
|
|
||||||
|
|
||||||
#
|
|
||||||
# mmc/SD image
|
|
||||||
#
|
|
||||||
|
|
||||||
# in MB
|
|
||||||
HAIKU_BOARD_SDIMAGE_SIZE = 256 ;
|
|
||||||
|
|
||||||
# in MB
|
|
||||||
HAIKU_BOARD_SDIMAGE_FAT_SIZE = 32 ;
|
|
||||||
|
|
||||||
# autoboot script
|
|
||||||
HAIKU_BOARD_SDIMAGE_UBOOT_SCRIPT_NAME = boot.scr ;
|
|
||||||
HAIKU_BOARD_SDIMAGE_UBOOT_SCRIPT = "\
|
|
||||||
setenv bootargs debug_screen true; \
|
|
||||||
if mmc rescan; then \
|
|
||||||
fatload mmc 0 0x80100000 /fdt/$(HAIKU_BOARD_FDT_NAME).dtb ; \
|
|
||||||
fatload mmc 0 0x81200000 haiku-floppyboot.tgz.ub; \
|
|
||||||
fatload mmc 0 $(HAIKU_BOARD_LOADER_UIBASE) haiku_loader_linux.ub; \
|
|
||||||
bootm $(HAIKU_BOARD_LOADER_UIBASE) 0x81200000 0x80100000; \
|
|
||||||
fi" ;
|
|
||||||
|
|
||||||
HAIKU_BOARD_SDIMAGE_FILES =
|
|
||||||
$(mloFile)
|
|
||||||
$(ubootFile)
|
|
||||||
haiku_loader
|
|
||||||
haiku_loader.ub
|
|
||||||
haiku_loader_linux.ub
|
|
||||||
haiku_loader_nbsd.ub
|
|
||||||
haiku-floppyboot.tgz.ub
|
|
||||||
$(HAIKU_BOARD_SDIMAGE_UBOOT_SCRIPT_NAME)
|
|
||||||
;
|
|
||||||
|
|
||||||
|
|
||||||
#
|
|
||||||
# gcc flags for the specific cpu
|
|
||||||
#
|
|
||||||
|
|
||||||
local flags = -mcpu=cortex-a8 -mfpu=vfpv3 -mfloat-abi=hard ;
|
|
||||||
|
|
||||||
HAIKU_ASFLAGS_$(HAIKU_PACKAGING_ARCH) += $(flags) ;
|
|
||||||
HAIKU_CCFLAGS_$(HAIKU_PACKAGING_ARCH) += $(flags) ;
|
|
||||||
HAIKU_C++FLAGS_$(HAIKU_PACKAGING_ARCH) += $(flags) ;
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
# Raspberry Pi 2 board-specific definitions
|
|
||||||
|
|
||||||
HAIKU_BOARD_DESCRIPTION = "Raspberry Pi 2" ;
|
|
||||||
HAIKU_BOARD_FDT_NAME = "rpi2" ;
|
|
||||||
|
|
||||||
#
|
|
||||||
# Various hardcoded addresses
|
|
||||||
#
|
|
||||||
|
|
||||||
HAIKU_BOARD_LOADER_BASE = 0x00080000 ;
|
|
||||||
HAIKU_BOARD_LOADER_ENTRY_RAW = $(HAIKU_BOARD_LOADER_BASE) ;
|
|
||||||
HAIKU_BOARD_LOADER_ENTRY_NBSD = `printf \"obase=16;ibase=16;8 + %x\\n\" $(HAIKU_BOARD_LOADER_BASE)|bc` ;
|
|
||||||
HAIKU_BOARD_LOADER_ENTRY_LINUX = `printf \"obase=16;ibase=16;10 + %x\\n\" $(HAIKU_BOARD_LOADER_BASE)|bc` ;
|
|
||||||
|
|
||||||
#
|
|
||||||
# mmc/SD image
|
|
||||||
#
|
|
||||||
|
|
||||||
# u-boot image
|
|
||||||
HAIKU_BOARD_UBOOT_IMAGE_URL = https://github.com/haiku/firmware/raw/master/arm/rpi2 ;
|
|
||||||
ubootFile = [ DownloadFile u-boot.bin : $(HAIKU_BOARD_UBOOT_IMAGE_URL)/u-boot.bin ] ;
|
|
||||||
configFile = [ DownloadFile config.txt : $(HAIKU_BOARD_UBOOT_IMAGE_URL)/config.txt ] ;
|
|
||||||
|
|
||||||
# Raspberry Pi foundation loader
|
|
||||||
HAIKU_BOARD_FIRMWARE_URL = https://github.com/raspberrypi/firmware/raw/master/boot ;
|
|
||||||
bootcodeFile = [ DownloadFile bootcode.bin : $(HAIKU_BOARD_FIRMWARE_URL)/bootcode.bin ] ;
|
|
||||||
startFile = [ DownloadFile start.elf : $(HAIKU_BOARD_FIRMWARE_URL)/start.elf ] ;
|
|
||||||
licenseFile = [ DownloadFile LICENCE.broadcom : $(HAIKU_BOARD_FIRMWARE_URL)/LICENCE.broadcom ] ;
|
|
||||||
|
|
||||||
HAIKU_BOARD_FIRMWARE_FILES =
|
|
||||||
$(bootcodeFile)
|
|
||||||
$(startFile)
|
|
||||||
$(licenseFile)
|
|
||||||
;
|
|
||||||
|
|
||||||
HAIKU_BOARD_SDIMAGE_UBOOT_SCRIPT_NAME = boot.scr ;
|
|
||||||
HAIKU_BOARD_SDIMAGE_UBOOT_SCRIPT = "\
|
|
||||||
fatload mmc 0 ${fdt_addr_r} /fdt/$(HAIKU_BOARD_FDT_NAME).dtb \
|
|
||||||
fdt addr ${fdt_addr_r} \
|
|
||||||
fatload mmc 0 ${ramdisk_addr_r} haiku-floppyboot.tgz.ub \
|
|
||||||
fatload mmc 0 ${kernel_addr_r} haiku_loader_linux.ub \
|
|
||||||
bootm ${kernel_addr_r} ${ramdisk_addr_r} ${fdt_addr_r}" ;
|
|
||||||
|
|
||||||
HAIKU_BOARD_SDIMAGE_FAT_SIZE = 32 ;
|
|
||||||
HAIKU_BOARD_SDIMAGE_FILES =
|
|
||||||
$(HAIKU_BOARD_FIRMWARE_FILES)
|
|
||||||
$(configFile)
|
|
||||||
$(ubootFile)
|
|
||||||
haiku_loader_linux.ub
|
|
||||||
haiku-floppyboot.tgz.ub
|
|
||||||
$(HAIKU_BOARD_SDIMAGE_UBOOT_SCRIPT_NAME)
|
|
||||||
;
|
|
||||||
|
|
||||||
HAIKU_BOARD_SDIMAGE_SIZE = 128 ;
|
|
||||||
|
|
||||||
#
|
|
||||||
# gcc flags for the specific cpu
|
|
||||||
#
|
|
||||||
|
|
||||||
local flags = -march=armv7-a -mfloat-abi=hard ;
|
|
||||||
|
|
||||||
HAIKU_ASFLAGS_$(HAIKU_PACKAGING_ARCH) += $(flags) ;
|
|
||||||
HAIKU_CCFLAGS_$(HAIKU_PACKAGING_ARCH) += $(flags) ;
|
|
||||||
HAIKU_C++FLAGS_$(HAIKU_PACKAGING_ARCH) += $(flags) ;
|
|
||||||
|
|
||||||
# Workaround for ld using 32k for alignment despite forcing it in the config...
|
|
||||||
# should definitely not be needed!
|
|
||||||
HAIKU_KERNEL_LINKFLAGS +=
|
|
||||||
-Wl,-z -Wl,max-page-size=0x1000
|
|
||||||
-Wl,-z -Wl,common-page-size=0x1000 ;
|
|
||||||
HAIKU_LINKFLAGS_$(HAIKU_PACKAGING_ARCH) +=
|
|
||||||
-Wl,-z -Wl,max-page-size=0x1000
|
|
||||||
-Wl,-z -Wl,common-page-size=0x1000 ;
|
|
||||||
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
##### CPU Speed
|
|
||||||
#arm_freq 700
|
|
||||||
|
|
||||||
##### Memory layout
|
|
||||||
#gpu_mem 64
|
|
||||||
|
|
||||||
# Memory based on model.. overrides gpu_mem
|
|
||||||
#gpu_mem_256 64
|
|
||||||
#gpu_mem_512 64
|
|
||||||
|
|
||||||
##### Low level
|
|
||||||
kernel=haiku_loader
|
|
||||||
kernel_address=0x0
|
|
||||||
ramfsfile=haiku-floppyboot.tgz
|
|
||||||
ramfsaddr=0x04000000
|
|
||||||
|
|
||||||
# Skip boot tags for non-linux platforms
|
|
||||||
disable_commandline_tags=1
|
|
||||||
#device_tree=bcm2835.dtb
|
|
||||||
#device_tree_address=0x100
|
|
||||||
|
|
||||||
##### UART Settings
|
|
||||||
# Default is 115200
|
|
||||||
#init_uart_baud=9600
|
|
||||||
#init_uart_clock=
|
|
||||||
@@ -24,7 +24,7 @@ local kernelGenericDriverSources =
|
|||||||
;
|
;
|
||||||
|
|
||||||
local platform ;
|
local platform ;
|
||||||
for platform in [ MultiBootSubDirSetup u-boot efi ] {
|
for platform in [ MultiBootSubDirSetup efi ] {
|
||||||
on $(platform) {
|
on $(platform) {
|
||||||
DEFINES += _BOOT_MODE ;
|
DEFINES += _BOOT_MODE ;
|
||||||
BootMergeObject [ FGristFiles boot_arch_$(TARGET_KERNEL_ARCH).o ] :
|
BootMergeObject [ FGristFiles boot_arch_$(TARGET_KERNEL_ARCH).o ] :
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ local kernelGenericDriverSources =
|
|||||||
;
|
;
|
||||||
|
|
||||||
local platform ;
|
local platform ;
|
||||||
for platform in [ MultiBootSubDirSetup u-boot efi riscv ] {
|
for platform in [ MultiBootSubDirSetup efi riscv ] {
|
||||||
on $(platform) {
|
on $(platform) {
|
||||||
DEFINES += _BOOT_MODE ;
|
DEFINES += _BOOT_MODE ;
|
||||||
BootMergeObject [ FGristFiles boot_arch_$(TARGET_KERNEL_ARCH).o ] :
|
BootMergeObject [ FGristFiles boot_arch_$(TARGET_KERNEL_ARCH).o ] :
|
||||||
|
|||||||
@@ -1,48 +0,0 @@
|
|||||||
SubDir HAIKU_TOP src system boot platform u-boot arch arm ;
|
|
||||||
|
|
||||||
SubDirHdrs $(HAIKU_TOP) src system boot platform $(TARGET_BOOT_PLATFORM) ;
|
|
||||||
SubDirHdrs $(HAIKU_TOP) src system boot arch $(TARGET_KERNEL_ARCH_DIR) ;
|
|
||||||
SubDirHdrs $(HAIKU_TOP) src add-ons kernel bus_managers fdt ;
|
|
||||||
|
|
||||||
UseLibraryHeaders [ FDirName libfdt ] ;
|
|
||||||
|
|
||||||
UsePrivateSystemHeaders ;
|
|
||||||
UsePrivateHeaders kernel [ FDirName kernel platform u-boot ] ;
|
|
||||||
UsePrivateHeaders kernel [ FDirName kernel arch $(TARGET_KERNEL_ARCH_DIR) ]
|
|
||||||
[ FDirName kernel boot platform $(HAIKU_BOOT_PLATFORM) ] ;
|
|
||||||
|
|
||||||
SubDirC++Flags -fno-rtti ;
|
|
||||||
|
|
||||||
# Things we borrow from the kernel due to lack of bios services
|
|
||||||
local kernelArchDriverSources =
|
|
||||||
#arch_uart_8250.cpp
|
|
||||||
arch_uart_8250_omap.cpp
|
|
||||||
arch_uart_pl011.cpp
|
|
||||||
;
|
|
||||||
|
|
||||||
BootMergeObject boot_platform_u-boot_arm.o :
|
|
||||||
# must come first to have _start_* at correct locations
|
|
||||||
shell.S
|
|
||||||
|
|
||||||
# Kernel entry calls
|
|
||||||
arch_start_kernel.S
|
|
||||||
|
|
||||||
# Framebuffer drivers
|
|
||||||
arch_framebuffer_920.cpp
|
|
||||||
arch_framebuffer_bcm2835.cpp
|
|
||||||
arch_framebuffer_omap3.cpp
|
|
||||||
arch_framebuffer_pxa.cpp
|
|
||||||
|
|
||||||
$(kernelArchDriverSources)
|
|
||||||
|
|
||||||
# Mailbox drivers
|
|
||||||
arch_mailbox_bcm2835.cpp
|
|
||||||
|
|
||||||
# u-boot mmu setup
|
|
||||||
arch_mmu.cpp
|
|
||||||
;
|
|
||||||
|
|
||||||
SEARCH on [ FGristFiles $(kernelArchDriverSources) ]
|
|
||||||
= [ FDirName $(HAIKU_TOP) src system kernel arch $(TARGET_KERNEL_ARCH_DIR) ] ;
|
|
||||||
#SEARCH on [ FGristFiles arch_cpu_asm.S ]
|
|
||||||
# = [ FDirName $(HAIKU_TOP) src system kernel arch $(TARGET_KERNEL_ARCH_DIR) ] ;
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2011-2012 Haiku, Inc. All rights reserved.
|
|
||||||
* Distributed under the terms of the MIT License.
|
|
||||||
*
|
|
||||||
* Authors:
|
|
||||||
* Alexander von Gluck IV, [email protected]
|
|
||||||
*/
|
|
||||||
#ifndef _ARCH_FRAMEBUFFER_H
|
|
||||||
#define _ARCH_FRAMEBUFFER_H
|
|
||||||
|
|
||||||
|
|
||||||
#include <boot/platform.h>
|
|
||||||
#include <SupportDefs.h>
|
|
||||||
|
|
||||||
|
|
||||||
#define TRACE_VIDEO
|
|
||||||
#ifdef TRACE_VIDEO
|
|
||||||
# define TRACE(x...) dprintf(x)
|
|
||||||
# define CALLED() dprintf("%s()\n", __func__);
|
|
||||||
#else
|
|
||||||
# define TRACE(x...) ;
|
|
||||||
# define CALLED() ;
|
|
||||||
#endif
|
|
||||||
#define ERROR(x...) dprintf(x)
|
|
||||||
|
|
||||||
|
|
||||||
class ArchFramebuffer {
|
|
||||||
public:
|
|
||||||
ArchFramebuffer(addr_t base)
|
|
||||||
:
|
|
||||||
fBase(base) {};
|
|
||||||
~ArchFramebuffer() {};
|
|
||||||
|
|
||||||
virtual status_t Init() { return B_OK; };
|
|
||||||
virtual status_t Probe() { return B_OK; };
|
|
||||||
virtual status_t SetDefaultMode() { return B_OK; };
|
|
||||||
virtual status_t SetVideoMode(int width, int height, int depth)
|
|
||||||
{ return B_OK; };
|
|
||||||
|
|
||||||
virtual addr_t Base() { return fBase; };
|
|
||||||
addr_t PhysicalBase() { return fPhysicalBase; };
|
|
||||||
size_t Size() { return fSize; };
|
|
||||||
|
|
||||||
int Width() { return fCurrentWidth; };
|
|
||||||
int Height() { return fCurrentHeight; };
|
|
||||||
int Depth() { return fCurrentDepth; };
|
|
||||||
int BytesPerRow() { return fCurrentBytesPerRow; };
|
|
||||||
|
|
||||||
protected:
|
|
||||||
addr_t fBase;
|
|
||||||
phys_addr_t fPhysicalBase;
|
|
||||||
size_t fSize;
|
|
||||||
int fCurrentWidth;
|
|
||||||
int fCurrentHeight;
|
|
||||||
int fCurrentDepth;
|
|
||||||
int fCurrentBytesPerRow;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* _ARCH_FRAMEBUFFER_H */
|
|
||||||
@@ -1,96 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2009-2012 Haiku, Inc. All rights reserved.
|
|
||||||
* Distributed under the terms of the MIT License.
|
|
||||||
*
|
|
||||||
* Authors:
|
|
||||||
* François Revol, [email protected]
|
|
||||||
* Alexander von Gluck IV, [email protected]
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "arch_framebuffer.h"
|
|
||||||
|
|
||||||
#include <arch/cpu.h>
|
|
||||||
#include <boot/stage2.h>
|
|
||||||
#include <boot/platform.h>
|
|
||||||
#include <boot/menu.h>
|
|
||||||
#include <boot/kernel_args.h>
|
|
||||||
#include <boot/platform/generic/video.h>
|
|
||||||
#include <drivers/driver_settings.h>
|
|
||||||
|
|
||||||
|
|
||||||
class ArchFBArm920 : public ArchFramebuffer {
|
|
||||||
public:
|
|
||||||
ArchFBArm920(addr_t base)
|
|
||||||
: ArchFramebuffer(base) {}
|
|
||||||
~ArchFBArm920() {}
|
|
||||||
status_t Init();
|
|
||||||
status_t Probe();
|
|
||||||
status_t SetDefaultMode();
|
|
||||||
status_t SetVideoMode(int width, int height, int depth);
|
|
||||||
};
|
|
||||||
|
|
||||||
extern "C" ArchFramebuffer *arch_get_fb_arm_920(addr_t base)
|
|
||||||
{
|
|
||||||
return new ArchFBArm920(base);
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t
|
|
||||||
ArchFBArm920::Init()
|
|
||||||
{
|
|
||||||
gKernelArgs.frame_buffer.enabled = true;
|
|
||||||
|
|
||||||
#warning TODO: ARM920 init
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
ArchFBArm920::Probe()
|
|
||||||
{
|
|
||||||
#if 0
|
|
||||||
// TODO: More dynamic framebuffer base?
|
|
||||||
if (!fBase) {
|
|
||||||
int err = platform_allocate_region(&gFrameBufferBase,
|
|
||||||
gKernelArgs.frame_buffer.physical_buffer.size, 0, false);
|
|
||||||
if (err < B_OK)
|
|
||||||
return err;
|
|
||||||
gKernelArgs.frame_buffer.physical_buffer.start
|
|
||||||
= (addr_t)gFrameBufferBase;
|
|
||||||
dprintf("video framebuffer: %p\n", gFrameBufferBase);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
gKernelArgs.frame_buffer.physical_buffer.start = fBase;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
gKernelArgs.frame_buffer.depth = 16;
|
|
||||||
gKernelArgs.frame_buffer.width = 1024;
|
|
||||||
gKernelArgs.frame_buffer.height = 768;
|
|
||||||
gKernelArgs.frame_buffer.bytes_per_row = gKernelArgs.frame_buffer.width * 2;
|
|
||||||
gKernelArgs.frame_buffer.physical_buffer.size
|
|
||||||
= gKernelArgs.frame_buffer.width
|
|
||||||
* gKernelArgs.frame_buffer.height
|
|
||||||
* gKernelArgs.frame_buffer.depth / 8;
|
|
||||||
|
|
||||||
dprintf("video mode: %ux%ux%u\n", gKernelArgs.frame_buffer.width,
|
|
||||||
gKernelArgs.frame_buffer.height, gKernelArgs.frame_buffer.depth);
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
ArchFBArm920::SetDefaultMode()
|
|
||||||
{
|
|
||||||
return SetVideoMode(gKernelArgs.frame_buffer.width,
|
|
||||||
gKernelArgs.frame_buffer.height,
|
|
||||||
gKernelArgs.frame_buffer.depth);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
ArchFBArm920::SetVideoMode(int width, int height, int depth)
|
|
||||||
{
|
|
||||||
#warning TODO: ArchFBArm920 SetVideoMode
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
@@ -1,201 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2012-2015 Haiku, Inc. All rights reserved.
|
|
||||||
* Distributed under the terms of the MIT License.
|
|
||||||
*
|
|
||||||
* Authors:
|
|
||||||
* Michael Lotz, [email protected]
|
|
||||||
* François Revol, [email protected]
|
|
||||||
* Alexander von Gluck IV, [email protected]
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "arch_framebuffer.h"
|
|
||||||
|
|
||||||
#include <arch/arm/bcm283X.h>
|
|
||||||
#include <arch/cpu.h>
|
|
||||||
#include <boot/stage2.h>
|
|
||||||
#include <boot/platform.h>
|
|
||||||
#include <boot/menu.h>
|
|
||||||
#include <boot/kernel_args.h>
|
|
||||||
#include <boot/platform/generic/video.h>
|
|
||||||
#include <util/list.h>
|
|
||||||
#include <drivers/driver_settings.h>
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "arch_mailbox.h"
|
|
||||||
#include "fdt_support.h"
|
|
||||||
#include "mmu.h"
|
|
||||||
|
|
||||||
|
|
||||||
//XXX
|
|
||||||
extern "C" bool
|
|
||||||
mmu_get_virtual_mapping(addr_t virtualAddress, phys_addr_t *_physicalAddress);
|
|
||||||
|
|
||||||
extern "C" ArchMailbox*
|
|
||||||
arch_get_mailbox_arm_bcm2835(addr_t base);
|
|
||||||
|
|
||||||
|
|
||||||
extern void* gFDT;
|
|
||||||
|
|
||||||
|
|
||||||
struct framebuffer_config {
|
|
||||||
uint32 width;
|
|
||||||
uint32 height;
|
|
||||||
uint32 virtual_width;
|
|
||||||
uint32 virtual_height;
|
|
||||||
uint32 bytes_per_row; // from GPU
|
|
||||||
uint32 bits_per_pixel;
|
|
||||||
uint32 x_offset;
|
|
||||||
uint32 y_offset;
|
|
||||||
uint32 frame_buffer_address; // from GPU
|
|
||||||
uint32 screen_size; // from GPU
|
|
||||||
uint16 color_map[256];
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
static framebuffer_config sFramebufferConfig __attribute__((aligned(16)));
|
|
||||||
|
|
||||||
|
|
||||||
class ArchFBArmBCM2835 : public ArchFramebuffer {
|
|
||||||
public:
|
|
||||||
ArchFBArmBCM2835(addr_t base)
|
|
||||||
: ArchFramebuffer(base) {}
|
|
||||||
~ArchFBArmBCM2835() {}
|
|
||||||
|
|
||||||
virtual status_t Init();
|
|
||||||
virtual status_t Probe();
|
|
||||||
virtual status_t SetDefaultMode();
|
|
||||||
virtual status_t SetVideoMode(int width, int height, int depth);
|
|
||||||
private:
|
|
||||||
ArchMailbox* fMailbox;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
extern "C" ArchFramebuffer*
|
|
||||||
arch_get_fb_arm_bcm2835(addr_t base)
|
|
||||||
{
|
|
||||||
return new ArchFBArmBCM2835(base);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
ArchFBArmBCM2835::Init()
|
|
||||||
{
|
|
||||||
if (!gFDT) {
|
|
||||||
dprintf("ERROR: FDT access is unavailable!");
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
phys_addr_t mboxBase = fdt_get_device_reg_byname(gFDT, "/axi/mbox");
|
|
||||||
if (!mboxBase) {
|
|
||||||
dprintf("ERROR: /axi/mbox is unavailable!");
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
fMailbox = arch_get_mailbox_arm_bcm2835(mboxBase);
|
|
||||||
|
|
||||||
if (fMailbox == NULL) {
|
|
||||||
dprintf("ERROR: Broadcom mailbox is unavailable!");
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
gKernelArgs.frame_buffer.enabled = true;
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
ArchFBArmBCM2835::Probe()
|
|
||||||
{
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
ArchFBArmBCM2835::SetDefaultMode()
|
|
||||||
{
|
|
||||||
status_t result;
|
|
||||||
do {
|
|
||||||
result = SetVideoMode(1920, 1080, 16);
|
|
||||||
} while (result != B_OK);
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
ArchFBArmBCM2835::SetVideoMode(int width, int height, int depth)
|
|
||||||
{
|
|
||||||
//debug_assert(((uint32)&sFramebufferConfig & 0x0f) == 0);
|
|
||||||
|
|
||||||
sFramebufferConfig.width = width;
|
|
||||||
sFramebufferConfig.height = height;
|
|
||||||
sFramebufferConfig.virtual_width = sFramebufferConfig.width;
|
|
||||||
sFramebufferConfig.virtual_height = sFramebufferConfig.height;
|
|
||||||
sFramebufferConfig.bytes_per_row = 0; // from GPU
|
|
||||||
sFramebufferConfig.bits_per_pixel = depth;
|
|
||||||
sFramebufferConfig.x_offset = 0;
|
|
||||||
sFramebufferConfig.y_offset = 0;
|
|
||||||
sFramebufferConfig.frame_buffer_address = 0; // from GPU
|
|
||||||
sFramebufferConfig.screen_size = 0; // from GPU
|
|
||||||
|
|
||||||
if (depth < 16) {
|
|
||||||
const int colorMapEntries = sizeof(sFramebufferConfig.color_map)
|
|
||||||
/ sizeof(sFramebufferConfig.color_map[0]);
|
|
||||||
for (int i = 0; i < colorMapEntries; i++)
|
|
||||||
sFramebufferConfig.color_map[i] = 0x1111 * i;
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t result = fMailbox->Write(ARM_MAILBOX_CHANNEL_FRAMEBUFFER,
|
|
||||||
(uint32)&sFramebufferConfig | BCM283X_VIDEO_CORE_L2_COHERENT);
|
|
||||||
if (result != B_OK)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
uint32 value;
|
|
||||||
result = fMailbox->Read(ARM_MAILBOX_CHANNEL_FRAMEBUFFER, value);
|
|
||||||
if (result != B_OK)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
if (value != 0) {
|
|
||||||
dprintf("failed to configure framebuffer: %" B_PRIx32 "\n", value);
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sFramebufferConfig.frame_buffer_address == 0) {
|
|
||||||
dprintf("didn't get the framebuffer address\n");
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
//debug_assert(sFramebufferConfig.x_offset == 0
|
|
||||||
// && sFramebufferConfig.y_offset == 0
|
|
||||||
// && sFramebufferConfig.width == (uint32)width
|
|
||||||
// && sFramebufferConfig.height == (uint32)height
|
|
||||||
// && sFramebufferConfig.virtual_width == sFramebufferConfig.width
|
|
||||||
// && sFramebufferConfig.virtual_height == sFramebufferConfig.height
|
|
||||||
// && sFramebufferConfig.bits_per_pixel == (uint32)depth
|
|
||||||
// && sFramebufferConfig.bytes_per_row
|
|
||||||
// >= sFramebufferConfig.bits_per_pixel / 8
|
|
||||||
// * sFramebufferConfig.width
|
|
||||||
// && sFramebufferConfig.screen_size >= sFramebufferConfig.bytes_per_row
|
|
||||||
// * sFramebufferConfig.height);
|
|
||||||
|
|
||||||
fPhysicalBase
|
|
||||||
= BCM283X_BUS_TO_PHYSICAL(sFramebufferConfig.frame_buffer_address);
|
|
||||||
fSize = sFramebufferConfig.screen_size;
|
|
||||||
|
|
||||||
fBase = (addr_t)mmu_map_physical_memory(fPhysicalBase, fSize, kDefaultPageFlags);
|
|
||||||
|
|
||||||
dprintf("video framebuffer: va: %p pa: %p\n", (void *)fBase,
|
|
||||||
(void *)fPhysicalBase);
|
|
||||||
|
|
||||||
fCurrentWidth = width;
|
|
||||||
fCurrentHeight = height;
|
|
||||||
fCurrentDepth = depth;
|
|
||||||
fCurrentBytesPerRow = sFramebufferConfig.bytes_per_row;
|
|
||||||
|
|
||||||
gKernelArgs.frame_buffer.physical_buffer.start = (addr_t)fPhysicalBase;
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,383 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2009-2012 Haiku, Inc. All rights reserved.
|
|
||||||
* Distributed under the terms of the MIT License.
|
|
||||||
*
|
|
||||||
* Authors:
|
|
||||||
* François Revol, [email protected]
|
|
||||||
* Alexander von Gluck IV, [email protected]
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "arch_framebuffer.h"
|
|
||||||
|
|
||||||
#include <arch/arm/omap3.h>
|
|
||||||
#include <arch/cpu.h>
|
|
||||||
#include <boot/stage2.h>
|
|
||||||
#include <boot/platform.h>
|
|
||||||
#include <boot/menu.h>
|
|
||||||
#include <boot/kernel_args.h>
|
|
||||||
#include <boot/platform/generic/video.h>
|
|
||||||
#include <util/list.h>
|
|
||||||
#include <drivers/driver_settings.h>
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "graphics/omap/omap3_regs.h"
|
|
||||||
|
|
||||||
|
|
||||||
//XXX
|
|
||||||
extern "C" addr_t mmu_map_physical_memory(addr_t physicalAddress, size_t size,
|
|
||||||
uint32 flags);
|
|
||||||
extern "C" bool
|
|
||||||
mmu_get_virtual_mapping(addr_t virtualAddress, phys_addr_t *_physicalAddress);
|
|
||||||
|
|
||||||
|
|
||||||
#define write_io_32(a, v) ((*(vuint32 *)a) = v)
|
|
||||||
#define read_io_32(a) (*(vuint32 *)a)
|
|
||||||
|
|
||||||
#define dumpr(a) dprintf("LCC:%s:0x%lx\n", #a, read_io_32(a))
|
|
||||||
|
|
||||||
|
|
||||||
class ArchFBArmOmap3 : public ArchFramebuffer {
|
|
||||||
public:
|
|
||||||
ArchFBArmOmap3(addr_t base)
|
|
||||||
: ArchFramebuffer(base) {}
|
|
||||||
~ArchFBArmOmap3() {}
|
|
||||||
|
|
||||||
status_t Init();
|
|
||||||
status_t Probe();
|
|
||||||
status_t SetDefaultMode();
|
|
||||||
status_t SetVideoMode(int width, int height, int depth);
|
|
||||||
};
|
|
||||||
|
|
||||||
extern "C" ArchFramebuffer *arch_get_fb_arm_omap3(addr_t base)
|
|
||||||
{
|
|
||||||
return new ArchFBArmOmap3(base);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
|
||||||
|
|
||||||
|
|
||||||
struct video_mode {
|
|
||||||
short width, height;
|
|
||||||
const char *name;
|
|
||||||
uint32 dispc_timing_h;
|
|
||||||
uint32 dispc_timing_v;
|
|
||||||
uint32 dispc_divisor;
|
|
||||||
uint32 dss_divisor;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Master clock (PLL4) is 864 Mhz, and changing it is a pita since it
|
|
||||||
// cascades to other devices.
|
|
||||||
// Pixel clock is 864 / cm_clksel_dss.dss1_alwan_fclk / dispc_divisor.divisor.pcd
|
|
||||||
// So most of these modes are just approximate (1280x1024 is correct)
|
|
||||||
// List must be in ascending order.
|
|
||||||
struct video_mode modes[] = {
|
|
||||||
{
|
|
||||||
640, 480, "640x480-71",
|
|
||||||
(128 << DISPCB_HBP) | (24 << DISPCB_HFP) | (40 << DISPCB_HSW),
|
|
||||||
(28 << DISPCB_VBP) | (9 << DISPCB_VFP) | (3 << DISPCB_VSW),
|
|
||||||
2, 14
|
|
||||||
},
|
|
||||||
{
|
|
||||||
800, 600, "800x600-59",
|
|
||||||
(88 << DISPCB_HBP) | (40 << DISPCB_HFP) | (128 << DISPCB_HSW),
|
|
||||||
(23 << DISPCB_VBP) | (1 << DISPCB_VFP) | (4 << DISPCB_VSW),
|
|
||||||
2, 11
|
|
||||||
},
|
|
||||||
{
|
|
||||||
1024, 768, "1024x768-61",
|
|
||||||
(160 << DISPCB_HBP) | (24 << DISPCB_HFP) | (136 << DISPCB_HSW),
|
|
||||||
(29 << DISPCB_VBP) | (3 << DISPCB_VFP) | (6 << DISPCB_VSW),
|
|
||||||
1, 13
|
|
||||||
},
|
|
||||||
{
|
|
||||||
1280, 1024, "1280x1024-60",
|
|
||||||
(248 << DISPCB_HBP) | (48 << DISPCB_HFP) | (112 << DISPCB_HSW),
|
|
||||||
(38 << DISPCB_VBP) | (1 << DISPCB_VFP) | (3 << DISPCB_VSW),
|
|
||||||
1, 8
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
setaddr(uint32 reg, unsigned int v)
|
|
||||||
{
|
|
||||||
*((volatile uint32 *)(reg)) = v;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
modaddr(unsigned int reg, unsigned int m, unsigned int v)
|
|
||||||
{
|
|
||||||
uint32 o;
|
|
||||||
|
|
||||||
o = *((volatile uint32 *)(reg));
|
|
||||||
o &= ~m;
|
|
||||||
o |= v;
|
|
||||||
*((volatile uint32 *)(reg)) = o;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static inline
|
|
||||||
void setreg(uint32 base, unsigned int reg, unsigned int v)
|
|
||||||
{
|
|
||||||
*((volatile uint32 *)(base + reg)) = v;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static inline
|
|
||||||
uint32 readreg(uint32 base, unsigned int reg)
|
|
||||||
{
|
|
||||||
return *((volatile uint32 *)(base + reg));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
modreg(uint32 base, unsigned int reg, unsigned int m, unsigned int v)
|
|
||||||
{
|
|
||||||
uint32 o;
|
|
||||||
|
|
||||||
o = *((volatile uint32 *)(base + reg));
|
|
||||||
o &= ~m;
|
|
||||||
o |= v;
|
|
||||||
*((volatile uint32 *)(base + reg)) = o;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// init beagle gpio for video
|
|
||||||
static void
|
|
||||||
omap_beagle_init(void)
|
|
||||||
{
|
|
||||||
// setup GPIO stuff, i can't find any references to these
|
|
||||||
setreg(GPIO1_BASE, GPIO_OE, 0xfefffedf);
|
|
||||||
setreg(GPIO1_BASE, GPIO_SETDATAOUT, 0x01000120);
|
|
||||||
// DVI-D is enabled by GPIO 170?
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
omap_clock_init(void)
|
|
||||||
{
|
|
||||||
// sets pixel clock to 72MHz
|
|
||||||
|
|
||||||
// sys_clk = 26.0 Mhz
|
|
||||||
// DPLL4 = sys_clk * 432 / 13 = 864
|
|
||||||
// DSS1_ALWON_FCLK = 864 / 6 = 144
|
|
||||||
// Pixel clock (DISPC_DIVISOR) = 144 / 2 = 72Mhz
|
|
||||||
// and also VENC clock = 864 / 16 = 54MHz
|
|
||||||
|
|
||||||
// The clock multiplier/divider cannot be changed
|
|
||||||
// without affecting other system clocks - do don't.
|
|
||||||
|
|
||||||
// pll4 clock multiplier/divider
|
|
||||||
setaddr(CM_CLKSEL2_PLL, (432 << 8) | 12);
|
|
||||||
// tv clock divider, dss1 alwon fclk divider
|
|
||||||
setaddr(CM_CLKSEL_DSS, (16 << 8) | 6);
|
|
||||||
// core/peripheral PLL to 1MHz
|
|
||||||
setaddr(CM_CLKEN_PLL, 0x00370037);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
omap_dss_init(void)
|
|
||||||
{
|
|
||||||
setreg(DSS_BASE, DSS_SYSCONFIG, DSS_AUTOIDLE);
|
|
||||||
// Select DSS1 ALWON as clock source
|
|
||||||
setreg(DSS_BASE, DSS_CONTROL, DSS_VENC_OUT_SEL | DSS_DAC_POWERDN_BGZ
|
|
||||||
| DSS_DAC_DEMEN | DSS_VENC_CLOCK_4X_ENABLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
omap_dispc_init(void)
|
|
||||||
{
|
|
||||||
uint32 DISPC = DISPC_BASE;
|
|
||||||
|
|
||||||
setreg(DISPC, DISPC_SYSCONFIG,
|
|
||||||
DISPC_MIDLEMODE_SMART
|
|
||||||
| DISPC_SIDLEMODE_SMART
|
|
||||||
| DISPC_ENWAKEUP
|
|
||||||
| DISPC_AUTOIDLE);
|
|
||||||
|
|
||||||
setreg(DISPC, DISPC_CONFIG, DISPC_LOADMODE_FRAME);
|
|
||||||
|
|
||||||
// LCD default colour = black
|
|
||||||
setreg(DISPC, DISPC_DEFAULT_COLOR0, 0x000000);
|
|
||||||
|
|
||||||
setreg(DISPC, DISPC_POL_FREQ,
|
|
||||||
DISPC_POL_IPC
|
|
||||||
| DISPC_POL_IHS
|
|
||||||
| DISPC_POL_IVS
|
|
||||||
| (2<<DISPCB_POL_ACBI)
|
|
||||||
| (8<<DISPCB_POL_ACB));
|
|
||||||
|
|
||||||
// Set pixel clock divisor = 2
|
|
||||||
setreg(DISPC, DISPC_DIVISOR,
|
|
||||||
(1<<DISPCB_DIVISOR_LCD)
|
|
||||||
| (2<<DISPCB_DIVISOR_PCD));
|
|
||||||
|
|
||||||
// Disable graphical output
|
|
||||||
setreg(DISPC, DISPC_GFX_ATTRIBUTES, 0);
|
|
||||||
|
|
||||||
// Turn on the LCD output
|
|
||||||
setreg(DISPC, DISPC_CONTROL,
|
|
||||||
DISPC_GPOUT1
|
|
||||||
| DISPC_GPOUT0
|
|
||||||
| DISPC_TFTDATALINES_24
|
|
||||||
| DISPC_STDITHERENABLE
|
|
||||||
| DISPC_GOLCD
|
|
||||||
| DISPC_STNTFT
|
|
||||||
| DISPC_LCDENABLE
|
|
||||||
);
|
|
||||||
|
|
||||||
while ((readreg(DISPC, DISPC_CONTROL) & DISPC_GOLCD))
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
omap_set_lcd_mode(int w, int h)
|
|
||||||
{
|
|
||||||
uint32 DISPC = DISPC_BASE;
|
|
||||||
unsigned int i;
|
|
||||||
struct video_mode *m;
|
|
||||||
|
|
||||||
dprintf("omap3: set_lcd_mode %d,%d\n", w, h);
|
|
||||||
|
|
||||||
for (i = 0; i < sizeof(modes) / sizeof(modes[0]); i++) {
|
|
||||||
if (w <= modes[i].width
|
|
||||||
&& h <= modes[i].height)
|
|
||||||
goto found;
|
|
||||||
}
|
|
||||||
i -= 1;
|
|
||||||
found:
|
|
||||||
m = &modes[i];
|
|
||||||
|
|
||||||
dprintf("omap3: found mode[%s]\n", m->name);
|
|
||||||
|
|
||||||
setreg(DISPC, DISPC_SIZE_LCD, (m->width - 1) | ((m->height - 1) << 16));
|
|
||||||
setreg(DISPC, DISPC_TIMING_H, m->dispc_timing_h);
|
|
||||||
setreg(DISPC, DISPC_TIMING_V, m->dispc_timing_v);
|
|
||||||
|
|
||||||
modreg(DISPC, DISPC_DIVISOR, 0xffff, m->dispc_divisor);
|
|
||||||
modaddr(CM_CLKSEL_DSS, 0x3f, m->dss_divisor);
|
|
||||||
|
|
||||||
// Tell hardware to update, and wait for it
|
|
||||||
modreg(DISPC, DISPC_CONTROL,
|
|
||||||
DISPC_GOLCD,
|
|
||||||
DISPC_GOLCD);
|
|
||||||
|
|
||||||
while ((readreg(DISPC, DISPC_CONTROL) & DISPC_GOLCD))
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
omap_attach_framebuffer(addr_t data, int width, int height, int depth)
|
|
||||||
{
|
|
||||||
uint32 DISPC = DISPC_BASE;
|
|
||||||
uint32 gsize = ((height - 1) << 16) | (width - 1);
|
|
||||||
|
|
||||||
dprintf("omap3: attach bitmap (%d,%d) to screen\n", width, height);
|
|
||||||
|
|
||||||
setreg(DISPC, DISPC_GFX_BA0, (uint32)data);
|
|
||||||
setreg(DISPC, DISPC_GFX_BA1, (uint32)data);
|
|
||||||
setreg(DISPC, DISPC_GFX_POSITION, 0);
|
|
||||||
setreg(DISPC, DISPC_GFX_SIZE, gsize);
|
|
||||||
setreg(DISPC, DISPC_GFX_FIFO_THRESHOLD, (0x3ff << 16) | 0x3c0);
|
|
||||||
setreg(DISPC, DISPC_GFX_ROW_INC, 1);
|
|
||||||
setreg(DISPC, DISPC_GFX_PIXEL_INC, 1);
|
|
||||||
setreg(DISPC, DISPC_GFX_WINDOW_SKIP, 0);
|
|
||||||
setreg(DISPC, DISPC_GFX_ATTRIBUTES, DISPC_GFXFORMAT_RGB16
|
|
||||||
| DISPC_GFXBURSTSIZE_16x32 | DISPC_GFXENABLE);
|
|
||||||
|
|
||||||
// Tell hardware to update, and wait for it
|
|
||||||
modreg(DISPC, DISPC_CONTROL, DISPC_GOLCD, DISPC_GOLCD);
|
|
||||||
|
|
||||||
while ((readreg(DISPC, DISPC_CONTROL) & DISPC_GOLCD))
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
ArchFBArmOmap3::Init()
|
|
||||||
{
|
|
||||||
gKernelArgs.frame_buffer.enabled = true;
|
|
||||||
|
|
||||||
setreg(DISPC_BASE, DISPC_IRQENABLE, 0x00000);
|
|
||||||
setreg(DISPC_BASE, DISPC_IRQSTATUS, 0x1ffff);
|
|
||||||
|
|
||||||
omap_beagle_init();
|
|
||||||
omap_clock_init();
|
|
||||||
omap_dss_init();
|
|
||||||
omap_dispc_init();
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
ArchFBArmOmap3::Probe()
|
|
||||||
{
|
|
||||||
|
|
||||||
gKernelArgs.frame_buffer.depth = 16;
|
|
||||||
gKernelArgs.frame_buffer.width = 1024;
|
|
||||||
gKernelArgs.frame_buffer.height = 768;
|
|
||||||
gKernelArgs.frame_buffer.bytes_per_row = gKernelArgs.frame_buffer.width * 2;
|
|
||||||
gKernelArgs.frame_buffer.physical_buffer.size
|
|
||||||
= gKernelArgs.frame_buffer.width
|
|
||||||
* gKernelArgs.frame_buffer.height
|
|
||||||
* gKernelArgs.frame_buffer.depth / 8;
|
|
||||||
|
|
||||||
#if 1
|
|
||||||
//dprintf("fBase %p\n", (void *)fBase);
|
|
||||||
if (!fBase || true) {
|
|
||||||
fBase = 0;
|
|
||||||
int err = platform_allocate_region((void **)&fBase,
|
|
||||||
gKernelArgs.frame_buffer.physical_buffer.size, 0, false);
|
|
||||||
if (err < B_OK) return err;
|
|
||||||
if (!mmu_get_virtual_mapping(fBase, &fPhysicalBase))
|
|
||||||
return B_ERROR;
|
|
||||||
gKernelArgs.frame_buffer.physical_buffer.start
|
|
||||||
= (addr_t)fPhysicalBase;
|
|
||||||
dprintf("video framebuffer: va: %p pa: %p\n", (void *)fBase,
|
|
||||||
(void *)fPhysicalBase);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
// TODO: More dynamic framebuffer base?
|
|
||||||
fPhysicalBase = fBase;
|
|
||||||
gKernelArgs.frame_buffer.physical_buffer.start = fPhysicalBase;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
TRACE("video mode: %ux%ux%u\n", gKernelArgs.frame_buffer.width,
|
|
||||||
gKernelArgs.frame_buffer.height, gKernelArgs.frame_buffer.depth);
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
ArchFBArmOmap3::SetVideoMode(int width, int height, int depth)
|
|
||||||
{
|
|
||||||
TRACE("%s: %dx%d@%d\n", __func__, width, height, depth);
|
|
||||||
|
|
||||||
omap_set_lcd_mode(width, height);
|
|
||||||
omap_attach_framebuffer(fPhysicalBase, width, height, depth);
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
ArchFBArmOmap3::SetDefaultMode()
|
|
||||||
{
|
|
||||||
CALLED();
|
|
||||||
|
|
||||||
return SetVideoMode(gKernelArgs.frame_buffer.width,
|
|
||||||
gKernelArgs.frame_buffer.height,
|
|
||||||
gKernelArgs.frame_buffer.depth);
|
|
||||||
}
|
|
||||||
@@ -1,230 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2009-2012 Haiku, Inc. All rights reserved.
|
|
||||||
* Distributed under the terms of the MIT License.
|
|
||||||
*
|
|
||||||
* Authors:
|
|
||||||
* François Revol, [email protected]
|
|
||||||
* Alexander von Gluck IV, [email protected]
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "arch_framebuffer.h"
|
|
||||||
|
|
||||||
#include <arch/arm/pxa270.h>
|
|
||||||
#include <arch/cpu.h>
|
|
||||||
#include <boot/stage2.h>
|
|
||||||
#include <boot/platform.h>
|
|
||||||
#include <boot/menu.h>
|
|
||||||
#include <boot/kernel_args.h>
|
|
||||||
#include <boot/platform/generic/video.h>
|
|
||||||
#include <util/list.h>
|
|
||||||
#include <drivers/driver_settings.h>
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
|
|
||||||
//XXX
|
|
||||||
extern "C" addr_t mmu_map_physical_memory(addr_t physicalAddress, size_t size,
|
|
||||||
uint32 flags);
|
|
||||||
|
|
||||||
|
|
||||||
class ArchFBArmPxa270 : public ArchFramebuffer {
|
|
||||||
public:
|
|
||||||
ArchFBArmPxa270(addr_t base)
|
|
||||||
: ArchFramebuffer(base) {}
|
|
||||||
~ArchFBArmPxa270() {}
|
|
||||||
status_t Init();
|
|
||||||
status_t Probe();
|
|
||||||
status_t SetDefaultMode();
|
|
||||||
status_t SetVideoMode(int width, int height, int depth);
|
|
||||||
};
|
|
||||||
|
|
||||||
extern "C" ArchFramebuffer *arch_get_fb_arm_pxa270(addr_t base)
|
|
||||||
{
|
|
||||||
return new ArchFBArmPxa270(base);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
|
||||||
|
|
||||||
|
|
||||||
#define write_io_32(a, v) ((*(vuint32 *)a) = v)
|
|
||||||
#define read_io_32(a) (*(vuint32 *)a)
|
|
||||||
|
|
||||||
#define dumpr(a) dprintf("LCC:%s:0x%lx\n", #a, read_io_32(a))
|
|
||||||
|
|
||||||
|
|
||||||
static struct pxa27x_lcd_dma_descriptor sVideoDMADesc;
|
|
||||||
static uint32 scratch[128] __attribute__((aligned(16)));
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
ArchFBArmPxa270::Init()
|
|
||||||
{
|
|
||||||
gKernelArgs.frame_buffer.enabled = true;
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
ArchFBArmPxa270::Probe()
|
|
||||||
{
|
|
||||||
CALLED();
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
// TODO: More dynamic framebuffer base?
|
|
||||||
if (!fBase) {
|
|
||||||
// XXX: realloc if larger !!!
|
|
||||||
err = platform_allocate_region(&gFrameBufferBase, fbSize, 0, false);
|
|
||||||
dprintf("error %08x\n", err);
|
|
||||||
if (err < B_OK)
|
|
||||||
return err;
|
|
||||||
gKernelArgs.frame_buffer.physical_buffer.start
|
|
||||||
= (addr_t)gFrameBufferBase;
|
|
||||||
/*
|
|
||||||
gFrameBufferBase = (void *)mmu_map_physical_memory(
|
|
||||||
0xa8000000, fbSize, 0);
|
|
||||||
if (gFrameBufferBase == NULL)
|
|
||||||
return B_NO_MEMORY;
|
|
||||||
gKernelArgs.frame_buffer.physical_buffer.start
|
|
||||||
= (addr_t)gFrameBufferBase; // 0xa8000000;
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
gKernelArgs.frame_buffer.physical_buffer.start = fBase;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
uint32 bppCode;
|
|
||||||
uint32 pixelFormat;
|
|
||||||
struct pxa27x_lcd_dma_descriptor *dma;
|
|
||||||
|
|
||||||
// check if LCD controller is enabled
|
|
||||||
if (!(read_io_32(LCCR0) & 0x00000001)) {
|
|
||||||
// not enabled, so return suggested mode
|
|
||||||
gKernelArgs.frame_buffer.depth = 32;
|
|
||||||
gKernelArgs.frame_buffer.width = 640;
|
|
||||||
gKernelArgs.frame_buffer.height = 480;
|
|
||||||
return B_NO_INIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
pixelFormat = bppCode = read_io_32(LCCR3);
|
|
||||||
bppCode = ((bppCode >> 26) & 0x08) | ((bppCode >> 24) & 0x07);
|
|
||||||
pixelFormat >>= 30;
|
|
||||||
|
|
||||||
dma = (struct pxa27x_lcd_dma_descriptor *)(read_io_32(FDADR0) & ~0x0f);
|
|
||||||
if (!dma)
|
|
||||||
return B_ERROR;
|
|
||||||
|
|
||||||
switch (bppCode) {
|
|
||||||
case 2:
|
|
||||||
gKernelArgs.frame_buffer.depth = 4;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
gKernelArgs.frame_buffer.depth = 8;
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
gKernelArgs.frame_buffer.depth = 16;
|
|
||||||
break;
|
|
||||||
case 9:
|
|
||||||
case 10:
|
|
||||||
gKernelArgs.frame_buffer.depth = 32; // RGB888
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
gKernelArgs.frame_buffer.physical_buffer.start = (dma->fsadr & ~0x0f);
|
|
||||||
gKernelArgs.frame_buffer.width = (read_io_32(LCCR1) & ((1 << 10) - 1)) + 1;
|
|
||||||
gKernelArgs.frame_buffer.height = (read_io_32(LCCR2) & ((1 << 10) - 1)) + 1;
|
|
||||||
gKernelArgs.frame_buffer.bytes_per_row = gKernelArgs.frame_buffer.width
|
|
||||||
* sizeof(uint32);
|
|
||||||
gKernelArgs.frame_buffer.physical_buffer.size
|
|
||||||
= gKernelArgs.frame_buffer.width
|
|
||||||
* gKernelArgs.frame_buffer.height
|
|
||||||
* gKernelArgs.frame_buffer.depth / 8;
|
|
||||||
|
|
||||||
dprintf("video mode: %ux%ux%u\n", gKernelArgs.frame_buffer.width,
|
|
||||||
gKernelArgs.frame_buffer.height, gKernelArgs.frame_buffer.depth);
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
ArchFBArmPxa270::SetVideoMode(int width, int height, int depth)
|
|
||||||
{
|
|
||||||
dprintf("%s(%d, %d, %d)\n", __FUNCTION__, width, height, depth);
|
|
||||||
|
|
||||||
void *fb;
|
|
||||||
uint32 fbSize = width * height * depth / 8;
|
|
||||||
|
|
||||||
fb = (void*)fBase;
|
|
||||||
|
|
||||||
dprintf("fb @ %p\n", fb);
|
|
||||||
|
|
||||||
sVideoDMADesc.fdadr = ((uint32)&sVideoDMADesc & ~0x0f) | 0x01;
|
|
||||||
sVideoDMADesc.fsadr = (uint32)(fb) & ~0x0f;
|
|
||||||
sVideoDMADesc.fidr = 0;
|
|
||||||
sVideoDMADesc.ldcmd = fbSize;
|
|
||||||
|
|
||||||
// if not already enabled, set a default mode
|
|
||||||
if (!(read_io_32(LCCR0) & 0x00000001)) {
|
|
||||||
int bpp;
|
|
||||||
int pdfor;
|
|
||||||
dprintf("Setting video mode\n");
|
|
||||||
switch (depth) {
|
|
||||||
case 4:
|
|
||||||
bpp = 2;
|
|
||||||
break;
|
|
||||||
case 8:
|
|
||||||
bpp = 3;
|
|
||||||
break;
|
|
||||||
case 16:
|
|
||||||
bpp = 3;
|
|
||||||
break;
|
|
||||||
case 32:
|
|
||||||
bpp = 9;
|
|
||||||
pdfor = 0x3;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return EINVAL;
|
|
||||||
}
|
|
||||||
write_io_32(LCCR1, (0 << 0) | (width - 1));
|
|
||||||
write_io_32(LCCR2, (0 << 0) | (height - 1));
|
|
||||||
write_io_32(LCCR3, (pdfor << 30) | ((bpp >> 3) << 29)
|
|
||||||
| ((bpp & 0x07) << 24));
|
|
||||||
write_io_32(FDADR0, sVideoDMADesc.fdadr);
|
|
||||||
write_io_32(LCCR0, read_io_32(LCCR0) | 0x01800001); // no ints +ENB
|
|
||||||
write_io_32(FBR0, sVideoDMADesc.fdadr);
|
|
||||||
dumpr(LCCR0);
|
|
||||||
dumpr(LCCR1);
|
|
||||||
dumpr(LCCR2);
|
|
||||||
dumpr(LCCR3);
|
|
||||||
dumpr(LCCR4);
|
|
||||||
} else
|
|
||||||
return B_OK; // assume we're already setup
|
|
||||||
|
|
||||||
// clear the video memory
|
|
||||||
memset((void *)fb, 0, fbSize);
|
|
||||||
|
|
||||||
// XXX test pattern
|
|
||||||
for (int i = 0; i < 128; i++) {
|
|
||||||
((uint32 *)fb)[i + 16] = 0x000000ff << ((i%4) * 8);
|
|
||||||
scratch[i] = 0x000000ff << ((i%4) * 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
// update framebuffer descriptor
|
|
||||||
return Probe();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
ArchFBArmPxa270::SetDefaultMode()
|
|
||||||
{
|
|
||||||
CALLED();
|
|
||||||
return SetVideoMode(gKernelArgs.frame_buffer.width,
|
|
||||||
gKernelArgs.frame_buffer.height,
|
|
||||||
gKernelArgs.frame_buffer.depth);
|
|
||||||
}
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2011-2015 Haiku, Inc. All rights reserved.
|
|
||||||
* Distributed under the terms of the MIT License.
|
|
||||||
*
|
|
||||||
* Authors:
|
|
||||||
* Alexander von Gluck IV, [email protected]
|
|
||||||
*/
|
|
||||||
#ifndef _ARCH_MAILBOX_H
|
|
||||||
#define _ARCH_MAILBOX_H
|
|
||||||
|
|
||||||
|
|
||||||
#include <boot/platform.h>
|
|
||||||
#include <SupportDefs.h>
|
|
||||||
|
|
||||||
|
|
||||||
#define TRACE_MAILBOX
|
|
||||||
#ifdef TRACE_MAILBOX
|
|
||||||
# define TRACE(x...) dprintf(x)
|
|
||||||
# define CALLED() dprintf("%s()\n", __func__);
|
|
||||||
#else
|
|
||||||
# define TRACE(x...) ;
|
|
||||||
# define CALLED() ;
|
|
||||||
#endif
|
|
||||||
#define ERROR(x...) dprintf(x)
|
|
||||||
|
|
||||||
|
|
||||||
class ArchMailbox {
|
|
||||||
public:
|
|
||||||
ArchMailbox(addr_t base)
|
|
||||||
:
|
|
||||||
fBase(base) {};
|
|
||||||
~ArchMailbox() {};
|
|
||||||
|
|
||||||
virtual status_t Init() { return B_OK; };
|
|
||||||
virtual status_t Probe() { return B_OK; };
|
|
||||||
|
|
||||||
virtual addr_t Base() { return fBase; };
|
|
||||||
addr_t PhysicalBase() { return fPhysicalBase; };
|
|
||||||
|
|
||||||
virtual status_t Write(uint8 channel, uint32 value) { return B_OK; };
|
|
||||||
virtual status_t Read(uint8 channel, uint32& value) { return B_OK; };
|
|
||||||
|
|
||||||
|
|
||||||
protected:
|
|
||||||
addr_t fBase;
|
|
||||||
addr_t fPhysicalBase;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* _ARCH_MAILBOX_H */
|
|
||||||
@@ -1,98 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2012 Haiku, Inc. All rights reserved.
|
|
||||||
* Distributed under the terms of the MIT License.
|
|
||||||
*
|
|
||||||
* Authors:
|
|
||||||
* Michael Lotz, [email protected]
|
|
||||||
* François Revol, [email protected]
|
|
||||||
* Alexander von Gluck IV, [email protected]
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "arch_mailbox.h"
|
|
||||||
|
|
||||||
#include <atomic>
|
|
||||||
#include <arch/arm/bcm283X.h>
|
|
||||||
|
|
||||||
#include "arch_cpu.h"
|
|
||||||
|
|
||||||
|
|
||||||
class ArchMailboxArmBCM2835 final : public ArchMailbox {
|
|
||||||
public:
|
|
||||||
ArchMailboxArmBCM2835(addr_t base)
|
|
||||||
:
|
|
||||||
ArchMailbox(base) {}
|
|
||||||
~ArchMailboxArmBCM2835() {}
|
|
||||||
|
|
||||||
virtual status_t Write(uint8 channel, uint32 value) override;
|
|
||||||
virtual status_t Read(uint8 channel, uint32& value) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
auto& GetRegister(unsigned reg);
|
|
||||||
void RegisterWrite(addr_t reg, uint32 value);
|
|
||||||
uint32 RegisterRead(addr_t reg);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
extern "C" ArchMailbox*
|
|
||||||
arch_get_mailbox_arm_bcm2835(addr_t base)
|
|
||||||
{
|
|
||||||
return new ArchMailboxArmBCM2835(base);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
ArchMailboxArmBCM2835::Write(uint8 channel, uint32 value)
|
|
||||||
{
|
|
||||||
// We have to wait for the mailbox to drain if it is marked full.
|
|
||||||
while ((RegisterRead(ARM_MAILBOX_STATUS) & ARM_MAILBOX_FULL) != 0)
|
|
||||||
;
|
|
||||||
|
|
||||||
value &= ARM_MAILBOX_DATA_MASK;
|
|
||||||
RegisterWrite(ARM_MAILBOX_WRITE, value | channel);
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
ArchMailboxArmBCM2835::Read(uint8 channel, uint32& value)
|
|
||||||
{
|
|
||||||
while (true) {
|
|
||||||
// Wait for something to arrive in the mailbox.
|
|
||||||
if ((RegisterRead(ARM_MAILBOX_STATUS) & ARM_MAILBOX_EMPTY) != 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
value = RegisterRead(ARM_MAILBOX_READ);
|
|
||||||
if ((value & ARM_MAILBOX_CHANNEL_MASK) != channel) {
|
|
||||||
// Not for us, retry.
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
value &= ARM_MAILBOX_DATA_MASK;
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
inline auto&
|
|
||||||
ArchMailboxArmBCM2835::GetRegister(unsigned reg)
|
|
||||||
{
|
|
||||||
auto addr = fBase + reg;
|
|
||||||
return *reinterpret_cast<std::atomic<uint32_t>*>(addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
inline uint32
|
|
||||||
ArchMailboxArmBCM2835::RegisterRead(addr_t reg)
|
|
||||||
{
|
|
||||||
return GetRegister(reg).load(std::memory_order_acquire);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
inline void
|
|
||||||
ArchMailboxArmBCM2835::RegisterWrite(addr_t reg, uint32 value)
|
|
||||||
{
|
|
||||||
GetRegister(reg).store(value, std::memory_order_release);
|
|
||||||
}
|
|
||||||
@@ -1,816 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2004-2008, Axel Dörfler, [email protected].
|
|
||||||
* Based on code written by Travis Geiselbrecht for NewOS.
|
|
||||||
*
|
|
||||||
* Distributed under the terms of the MIT License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "mmu.h"
|
|
||||||
|
|
||||||
#include <boot/platform.h>
|
|
||||||
#include <boot/stdio.h>
|
|
||||||
#include <boot/kernel_args.h>
|
|
||||||
#include <boot/stage2.h>
|
|
||||||
#include <arch/cpu.h>
|
|
||||||
#include <arch_kernel.h>
|
|
||||||
#include <arm_mmu.h>
|
|
||||||
#include <kernel.h>
|
|
||||||
|
|
||||||
#include <OS.h>
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "fdt_support.h"
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#include <fdt.h>
|
|
||||||
#include <libfdt.h>
|
|
||||||
#include <libfdt_env.h>
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#define TRACE_MMU
|
|
||||||
#ifdef TRACE_MMU
|
|
||||||
# define TRACE(x) dprintf x
|
|
||||||
#else
|
|
||||||
# define TRACE(x) ;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define TRACE_MEMORY_MAP
|
|
||||||
// Define this to print the memory map to serial debug,
|
|
||||||
// You also need to define ENABLE_SERIAL in serial.cpp
|
|
||||||
// for output to work.
|
|
||||||
|
|
||||||
/*
|
|
||||||
TODO:
|
|
||||||
-recycle bit!
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*! The (physical) memory layout of the boot loader is currently as follows:
|
|
||||||
0x00000000 u-boot (run from NOR flash)
|
|
||||||
0xa0000000 u-boot stuff like kernel arguments afaik
|
|
||||||
0xa0100000 - 0xa0ffffff boot.tgz (up to 15MB probably never needed so big...)
|
|
||||||
0xa1000000 - 0xa1ffffff pagetables
|
|
||||||
0xa2000000 - ? code (up to 1MB)
|
|
||||||
0xa2100000 boot loader heap / free physical memory
|
|
||||||
|
|
||||||
The kernel is mapped at KERNEL_LOAD_BASE, all other stuff mapped by the
|
|
||||||
loader (kernel args, modules, driver settings, ...) comes after
|
|
||||||
0x80020000 which means that there is currently only 2 MB reserved for
|
|
||||||
the kernel itself (see kMaxKernelSize).
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
// 8 MB for the kernel, kernel args, modules, driver settings, ...
|
|
||||||
static const size_t kMaxKernelSize = 0x800000;
|
|
||||||
|
|
||||||
// Start and end of ourselfs (from ld script)
|
|
||||||
extern int _start, _end;
|
|
||||||
|
|
||||||
/*
|
|
||||||
*defines a block in memory
|
|
||||||
*/
|
|
||||||
struct memblock {
|
|
||||||
const char name[16];
|
|
||||||
// the name will be used for debugging etc later perhaps...
|
|
||||||
addr_t start;
|
|
||||||
// start of the block
|
|
||||||
addr_t end;
|
|
||||||
// end of the block
|
|
||||||
uint32 flags;
|
|
||||||
// which flags should be applied (device/normal etc..)
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
static struct memblock LOADER_MEMORYMAP[] = {
|
|
||||||
{
|
|
||||||
"RAM_kernel", // 8MB space for kernel, drivers etc
|
|
||||||
KERNEL_LOAD_BASE,
|
|
||||||
KERNEL_LOAD_BASE + kMaxKernelSize - 1,
|
|
||||||
ARM_MMU_L2_FLAG_C,
|
|
||||||
},
|
|
||||||
#ifdef FB_BASE
|
|
||||||
{
|
|
||||||
"framebuffer", // 2MB framebuffer ram
|
|
||||||
FB_BASE,
|
|
||||||
FB_BASE + FB_SIZE - 1,
|
|
||||||
ARM_MMU_L2_FLAG_AP_RW | ARM_MMU_L2_FLAG_C,
|
|
||||||
},
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
//static const uint32 kDefaultPageTableFlags = MMU_FLAG_READWRITE;
|
|
||||||
// not cached not buffered, R/W
|
|
||||||
|
|
||||||
static addr_t sNextPhysicalAddress = 0; //will be set by mmu_init
|
|
||||||
static addr_t sNextVirtualAddress = 0;
|
|
||||||
|
|
||||||
static addr_t sNextPageTableAddress = 0;
|
|
||||||
//the page directory is in front of the pagetable
|
|
||||||
static uint32 sPageTableRegionEnd = 0;
|
|
||||||
|
|
||||||
static uint32 sSmallPageType = ARM_MMU_L2_TYPE_SMALLEXT;
|
|
||||||
|
|
||||||
// working page directory and page table
|
|
||||||
static uint32 *sPageDirectory = 0 ;
|
|
||||||
//page directory has to be on a multiple of 16MB for
|
|
||||||
//some arm processors
|
|
||||||
|
|
||||||
|
|
||||||
static addr_t
|
|
||||||
get_next_virtual_address_aligned(size_t size, uint32 mask)
|
|
||||||
{
|
|
||||||
addr_t address = (sNextVirtualAddress) & mask;
|
|
||||||
sNextVirtualAddress = address + size;
|
|
||||||
|
|
||||||
return address;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static addr_t
|
|
||||||
get_next_physical_address_aligned(size_t size, uint32 mask)
|
|
||||||
{
|
|
||||||
addr_t address = sNextPhysicalAddress & mask;
|
|
||||||
sNextPhysicalAddress = address + size;
|
|
||||||
|
|
||||||
return address;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static addr_t
|
|
||||||
get_next_virtual_page(size_t pagesize)
|
|
||||||
{
|
|
||||||
return get_next_virtual_address_aligned(pagesize, 0xffffffc0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static addr_t
|
|
||||||
get_next_physical_page(size_t pagesize)
|
|
||||||
{
|
|
||||||
return get_next_physical_address_aligned(pagesize, 0xffffffc0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Set translation table base
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
mmu_set_TTBR(uint32 ttb)
|
|
||||||
{
|
|
||||||
ttb &= 0xffffc000;
|
|
||||||
asm volatile("MCR p15, 0, %[adr], c2, c0, 0"::[adr] "r" (ttb));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Flush the TLB
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
mmu_flush_TLB()
|
|
||||||
{
|
|
||||||
uint32 value = 0;
|
|
||||||
asm volatile("MCR p15, 0, %[c8format], c8, c7, 0"::[c8format] "r" (value));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Read MMU Control Register
|
|
||||||
*/
|
|
||||||
uint32
|
|
||||||
mmu_read_C1()
|
|
||||||
{
|
|
||||||
uint32 controlReg = 0;
|
|
||||||
asm volatile("MRC p15, 0, %[c1out], c1, c0, 0":[c1out] "=r" (controlReg));
|
|
||||||
return controlReg;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Write MMU Control Register
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
mmu_write_C1(uint32 value)
|
|
||||||
{
|
|
||||||
asm volatile("MCR p15, 0, %[c1in], c1, c0, 0"::[c1in] "r" (value));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Dump current MMU Control Register state
|
|
||||||
* For debugging, can be added to loader temporarly post-serial-init
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
mmu_dump_C1()
|
|
||||||
{
|
|
||||||
uint32 cpValue = mmu_read_C1();
|
|
||||||
|
|
||||||
dprintf("MMU CP15:c1 State:\n");
|
|
||||||
|
|
||||||
if ((cpValue & (1 << 0)) != 0)
|
|
||||||
dprintf(" - MMU Enabled\n");
|
|
||||||
else
|
|
||||||
dprintf(" - MMU Disabled\n");
|
|
||||||
|
|
||||||
if ((cpValue & (1 << 2)) != 0)
|
|
||||||
dprintf(" - Data Cache Enabled\n");
|
|
||||||
else
|
|
||||||
dprintf(" - Data Cache Disabled\n");
|
|
||||||
|
|
||||||
if ((cpValue & (1 << 3)) != 0)
|
|
||||||
dprintf(" - Write Buffer Enabled\n");
|
|
||||||
else
|
|
||||||
dprintf(" - Write Buffer Disabled\n");
|
|
||||||
|
|
||||||
if ((cpValue & (1 << 12)) != 0)
|
|
||||||
dprintf(" - Instruction Cache Enabled\n");
|
|
||||||
else
|
|
||||||
dprintf(" - Instruction Cache Disabled\n");
|
|
||||||
|
|
||||||
if ((cpValue & (1 << 13)) != 0)
|
|
||||||
dprintf(" - Vector Table @ 0xFFFF0000\n");
|
|
||||||
else
|
|
||||||
dprintf(" - Vector Table @ 0x00000000\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
mmu_write_DACR(uint32 value)
|
|
||||||
{
|
|
||||||
asm volatile("MCR p15, 0, %[c1in], c3, c0, 0"::[c1in] "r" (value));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static uint32 *
|
|
||||||
get_next_page_table(uint32 type)
|
|
||||||
{
|
|
||||||
TRACE(("get_next_page_table, sNextPageTableAddress 0x%" B_PRIxADDR
|
|
||||||
", sPageTableRegionEnd 0x%" B_PRIxADDR ", type 0x%" B_PRIx32 "\n",
|
|
||||||
sNextPageTableAddress, sPageTableRegionEnd, type));
|
|
||||||
|
|
||||||
size_t size = 0;
|
|
||||||
size_t entryCount = 0;
|
|
||||||
switch (type) {
|
|
||||||
case ARM_MMU_L1_TYPE_COARSE:
|
|
||||||
size = ARM_MMU_L2_COARSE_TABLE_SIZE;
|
|
||||||
entryCount = ARM_MMU_L2_COARSE_ENTRY_COUNT;
|
|
||||||
break;
|
|
||||||
case ARM_MMU_L1_TYPE_FINE:
|
|
||||||
size = ARM_MMU_L2_FINE_TABLE_SIZE;
|
|
||||||
entryCount = ARM_MMU_L2_FINE_ENTRY_COUNT;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
panic("asked for unknown page table type: %#" B_PRIx32 "\n", type);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
addr_t address = sNextPageTableAddress;
|
|
||||||
if (address < sPageTableRegionEnd)
|
|
||||||
sNextPageTableAddress += size;
|
|
||||||
else {
|
|
||||||
TRACE(("page table allocation outside of pagetable region!\n"));
|
|
||||||
address = get_next_physical_address_aligned(size, 0xffffffc0);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32 *pageTable = (uint32 *)address;
|
|
||||||
for (size_t i = 0; i < entryCount; i++)
|
|
||||||
pageTable[i] = 0;
|
|
||||||
|
|
||||||
return pageTable;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static uint32 *
|
|
||||||
get_or_create_page_table(addr_t address, uint32 type)
|
|
||||||
{
|
|
||||||
uint32 *pageTable = NULL;
|
|
||||||
uint32 pageDirectoryIndex = VADDR_TO_PDENT(address);
|
|
||||||
uint32 pageDirectoryEntry = sPageDirectory[pageDirectoryIndex];
|
|
||||||
|
|
||||||
uint32 entryType = pageDirectoryEntry & ARM_PDE_TYPE_MASK;
|
|
||||||
if (entryType == ARM_MMU_L1_TYPE_FAULT) {
|
|
||||||
// This page directory entry has not been set yet, allocate it.
|
|
||||||
pageTable = get_next_page_table(type);
|
|
||||||
sPageDirectory[pageDirectoryIndex] = (uint32)pageTable | type;
|
|
||||||
return pageTable;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (entryType != type) {
|
|
||||||
// This entry has been allocated with a different type!
|
|
||||||
panic("tried to reuse page directory entry %" B_PRIu32
|
|
||||||
" with different type (entry: %#" B_PRIx32 ", new type: %#" B_PRIx32
|
|
||||||
")\n", pageDirectoryIndex, pageDirectoryEntry, type);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (uint32 *)(pageDirectoryEntry & ARM_PDE_ADDRESS_MASK);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
mmu_map_identity(addr_t start, size_t end, int flags)
|
|
||||||
{
|
|
||||||
uint32 *pageTable = NULL;
|
|
||||||
uint32 pageTableIndex = 0;
|
|
||||||
|
|
||||||
start = ROUNDDOWN(start, B_PAGE_SIZE);
|
|
||||||
end = ROUNDUP(end, B_PAGE_SIZE);
|
|
||||||
|
|
||||||
TRACE(("mmu_map_identity: [ %" B_PRIxADDR " - %" B_PRIxADDR "]\n", start, end));
|
|
||||||
|
|
||||||
for (addr_t address = start; address < end; address += B_PAGE_SIZE) {
|
|
||||||
if (pageTable == NULL
|
|
||||||
|| pageTableIndex >= ARM_MMU_L2_COARSE_ENTRY_COUNT) {
|
|
||||||
pageTable = get_or_create_page_table(address,
|
|
||||||
ARM_MMU_L1_TYPE_COARSE);
|
|
||||||
pageTableIndex = VADDR_TO_PTENT(address);
|
|
||||||
}
|
|
||||||
|
|
||||||
pageTable[pageTableIndex++]
|
|
||||||
= address | flags | sSmallPageType;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
map_pages_loader()
|
|
||||||
{
|
|
||||||
for (uint32 i = 0; i < B_COUNT_OF(LOADER_MEMORYMAP); i++) {
|
|
||||||
|
|
||||||
TRACE(("BLOCK: %s START: %lx END %lx\n", LOADER_MEMORYMAP[i].name,
|
|
||||||
LOADER_MEMORYMAP[i].start, LOADER_MEMORYMAP[i].end));
|
|
||||||
|
|
||||||
addr_t address = LOADER_MEMORYMAP[i].start;
|
|
||||||
ASSERT((address & ~ARM_PTE_ADDRESS_MASK) == 0);
|
|
||||||
|
|
||||||
mmu_map_identity(LOADER_MEMORYMAP[i].start, LOADER_MEMORYMAP[i].end,
|
|
||||||
LOADER_MEMORYMAP[i].flags);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//TODO:move this to generic/ ?
|
|
||||||
static status_t
|
|
||||||
fdt_map_memory_ranges(void* fdt, const char* path, bool physical = false)
|
|
||||||
{
|
|
||||||
int node;
|
|
||||||
const void *prop;
|
|
||||||
int len;
|
|
||||||
uint64 total;
|
|
||||||
|
|
||||||
dprintf("checking FDT for %s...\n", path);
|
|
||||||
node = fdt_path_offset(fdt, path);
|
|
||||||
|
|
||||||
total = 0;
|
|
||||||
|
|
||||||
int32 regAddressCells = 1;
|
|
||||||
int32 regSizeCells = 1;
|
|
||||||
fdt_get_cell_count(fdt, node, regAddressCells, regSizeCells);
|
|
||||||
|
|
||||||
prop = fdt_getprop(fdt, node, "reg", &len);
|
|
||||||
if (prop == NULL) {
|
|
||||||
dprintf("Unable to locate %s in FDT!\n", path);
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
const uint32 *p = (const uint32 *)prop;
|
|
||||||
for (int32 i = 0; len; i++) {
|
|
||||||
uint64 base;
|
|
||||||
uint64 size;
|
|
||||||
if (regAddressCells == 2)
|
|
||||||
base = fdt64_to_cpu(*(uint64_t *)p);
|
|
||||||
else
|
|
||||||
base = fdt32_to_cpu(*(uint32_t *)p);
|
|
||||||
p += regAddressCells;
|
|
||||||
if (regSizeCells == 2)
|
|
||||||
size = fdt64_to_cpu(*(uint64_t *)p);
|
|
||||||
else
|
|
||||||
size = fdt32_to_cpu(*(uint32_t *)p);
|
|
||||||
p += regSizeCells;
|
|
||||||
len -= sizeof(uint32) * (regAddressCells + regSizeCells);
|
|
||||||
|
|
||||||
if (size <= 0) {
|
|
||||||
dprintf("%ld: empty region\n", i);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
dprintf("%" B_PRIu32 ": base = %" B_PRIu64 ","
|
|
||||||
"size = %" B_PRIu64 "\n", i, base, size);
|
|
||||||
|
|
||||||
total += size;
|
|
||||||
|
|
||||||
if (physical) {
|
|
||||||
if (insert_physical_memory_range(base, size) != B_OK) {
|
|
||||||
dprintf("cannot map physical memory range "
|
|
||||||
"(num ranges = %" B_PRIu32 ")!\n",
|
|
||||||
gKernelArgs.num_physical_memory_ranges);
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
mmu_map_identity(base, base + size, ARM_MMU_L2_FLAG_B);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dprintf("total '%s' physical memory = %" B_PRId64 "MB\n", path,
|
|
||||||
total / (1024 * 1024));
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
fdt_map_peripheral(void* fdt)
|
|
||||||
{
|
|
||||||
if (fdt == NULL) {
|
|
||||||
dprintf("Invalid FDT provided to %s!", __func__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// map peripheral devices (such as uart) from fdt
|
|
||||||
|
|
||||||
#warning Map peripherals from the fdt we want to use in the bootloader!
|
|
||||||
// this assumes /pl011@9000000 which is the qemu virt uart
|
|
||||||
fdt_map_memory_ranges(fdt, "/pl011@9000000");
|
|
||||||
// this assumes /axi which is broadcom!
|
|
||||||
fdt_map_memory_ranges(fdt, "/axi");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
init_page_directory(void* fdt)
|
|
||||||
{
|
|
||||||
TRACE(("init_page_directory\n"));
|
|
||||||
|
|
||||||
gKernelArgs.arch_args.phys_pgdir =
|
|
||||||
gKernelArgs.arch_args.vir_pgdir = (uint32)sPageDirectory;
|
|
||||||
|
|
||||||
// clear out the page directory
|
|
||||||
for (uint32 i = 0; i < ARM_MMU_L1_TABLE_ENTRY_COUNT; i++)
|
|
||||||
sPageDirectory[i] = 0;
|
|
||||||
|
|
||||||
// map ourselfs first... just to make sure
|
|
||||||
mmu_map_identity((addr_t)&_start, (addr_t)&_end, ARM_MMU_L2_FLAG_C);
|
|
||||||
|
|
||||||
// map our page directory region (TODO should not be identity mapped)
|
|
||||||
mmu_map_identity((addr_t)sPageDirectory, sPageTableRegionEnd, ARM_MMU_L2_FLAG_C);
|
|
||||||
|
|
||||||
// map our well known / static pages
|
|
||||||
map_pages_loader();
|
|
||||||
|
|
||||||
// map our fdt peripherals
|
|
||||||
fdt_map_peripheral(fdt);
|
|
||||||
|
|
||||||
mmu_flush_TLB();
|
|
||||||
|
|
||||||
/* set up the translation table base */
|
|
||||||
mmu_set_TTBR((uint32)sPageDirectory);
|
|
||||||
|
|
||||||
mmu_flush_TLB();
|
|
||||||
|
|
||||||
/* set up the domain access register */
|
|
||||||
mmu_write_DACR(0xFFFFFFFF);
|
|
||||||
|
|
||||||
/* turn on the mmu */
|
|
||||||
mmu_write_C1(mmu_read_C1() | 0x1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*! Creates an entry to map the specified virtualAddress to the given
|
|
||||||
physicalAddress.
|
|
||||||
If the mapping goes beyond the current page table, it will allocate
|
|
||||||
a new one. If it cannot map the requested page, it panics.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
map_page(addr_t virtualAddress, addr_t physicalAddress, uint32 flags)
|
|
||||||
{
|
|
||||||
TRACE(("map_page: vaddr 0x%lx, paddr 0x%lx\n", virtualAddress,
|
|
||||||
physicalAddress));
|
|
||||||
|
|
||||||
if (virtualAddress < KERNEL_LOAD_BASE) {
|
|
||||||
panic("map_page: asked to map invalid page %p!\n",
|
|
||||||
(void *)virtualAddress);
|
|
||||||
}
|
|
||||||
|
|
||||||
physicalAddress &= ~(B_PAGE_SIZE - 1);
|
|
||||||
|
|
||||||
// map the page to the correct page table
|
|
||||||
uint32 *pageTable = get_or_create_page_table(virtualAddress,
|
|
||||||
ARM_MMU_L1_TYPE_COARSE);
|
|
||||||
|
|
||||||
uint32 pageTableIndex = VADDR_TO_PTENT(virtualAddress);
|
|
||||||
TRACE(("map_page: inserting pageTable %p, tableEntry 0x%" B_PRIx32
|
|
||||||
", physicalAddress 0x%" B_PRIxADDR "\n", pageTable, pageTableIndex,
|
|
||||||
physicalAddress));
|
|
||||||
|
|
||||||
pageTable[pageTableIndex] = physicalAddress | flags;
|
|
||||||
|
|
||||||
mmu_flush_TLB();
|
|
||||||
|
|
||||||
TRACE(("map_page: done\n"));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
|
||||||
|
|
||||||
|
|
||||||
extern "C" addr_t
|
|
||||||
mmu_map_physical_memory(addr_t physicalAddress, size_t size, uint32 flags)
|
|
||||||
{
|
|
||||||
TRACE(("mmu_map_physical_memory(phAddr=%lx, %lx, %lu)\n", physicalAddress, size, flags));
|
|
||||||
addr_t address = sNextVirtualAddress;
|
|
||||||
addr_t pageOffset = physicalAddress & (B_PAGE_SIZE - 1);
|
|
||||||
|
|
||||||
physicalAddress -= pageOffset;
|
|
||||||
if (pageOffset)
|
|
||||||
size += B_PAGE_SIZE;
|
|
||||||
|
|
||||||
for (addr_t offset = 0; offset < size; offset += B_PAGE_SIZE) {
|
|
||||||
map_page(get_next_virtual_page(B_PAGE_SIZE), physicalAddress + offset,
|
|
||||||
flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
return address + pageOffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
unmap_page(addr_t virtualAddress)
|
|
||||||
{
|
|
||||||
TRACE(("unmap_page(virtualAddress = %p)\n", (void *)virtualAddress));
|
|
||||||
|
|
||||||
if (virtualAddress < KERNEL_LOAD_BASE) {
|
|
||||||
panic("unmap_page: asked to unmap invalid page %p!\n",
|
|
||||||
(void *)virtualAddress);
|
|
||||||
}
|
|
||||||
|
|
||||||
// unmap the page from the correct page table
|
|
||||||
uint32 *pageTable
|
|
||||||
= (uint32 *)(sPageDirectory[VADDR_TO_PDENT(virtualAddress)]
|
|
||||||
& ARM_PDE_ADDRESS_MASK);
|
|
||||||
|
|
||||||
pageTable[VADDR_TO_PTENT(virtualAddress)] = 0;
|
|
||||||
|
|
||||||
mmu_flush_TLB();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// XXX: use phys_addr_t ?
|
|
||||||
extern "C" bool
|
|
||||||
mmu_get_virtual_mapping(addr_t virtualAddress, /*phys_*/addr_t *_physicalAddress)
|
|
||||||
{
|
|
||||||
if (virtualAddress < KERNEL_LOAD_BASE) {
|
|
||||||
panic("mmu_get_virtual_mapping: asked to lookup invalid page %p!\n",
|
|
||||||
(void *)virtualAddress);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// map the page to the correct page table
|
|
||||||
uint32 *pageTable = get_or_create_page_table(virtualAddress,
|
|
||||||
ARM_MMU_L1_TYPE_COARSE);
|
|
||||||
|
|
||||||
uint32 pageTableIndex = VADDR_TO_PTENT(virtualAddress);
|
|
||||||
|
|
||||||
*_physicalAddress = pageTable[pageTableIndex] & ~(B_PAGE_SIZE - 1);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
extern "C" void *
|
|
||||||
mmu_allocate(void *virtualAddress, size_t size)
|
|
||||||
{
|
|
||||||
TRACE(("mmu_allocate: requested vaddr: %p, next free vaddr: 0x%lx, size: "
|
|
||||||
"%ld\n", virtualAddress, sNextVirtualAddress, size));
|
|
||||||
|
|
||||||
size = (size + B_PAGE_SIZE - 1) / B_PAGE_SIZE;
|
|
||||||
// get number of pages to map
|
|
||||||
|
|
||||||
if (virtualAddress != NULL) {
|
|
||||||
// This special path is almost only useful for loading the
|
|
||||||
// kernel into memory; it will only allow you to map the
|
|
||||||
// 'kMaxKernelSize' bytes following the kernel base address.
|
|
||||||
// Also, it won't check for already mapped addresses, so
|
|
||||||
// you better know why you are here :)
|
|
||||||
addr_t address = (addr_t)virtualAddress;
|
|
||||||
|
|
||||||
// is the address within the valid range?
|
|
||||||
if (address < KERNEL_LOAD_BASE || address + size * B_PAGE_SIZE
|
|
||||||
>= KERNEL_LOAD_BASE + kMaxKernelSize) {
|
|
||||||
TRACE(("mmu_allocate in illegal range\n address: %" B_PRIx32
|
|
||||||
" KERNELBASE: %" B_PRIx32 " KERNEL_LOAD_BASE + kMaxKernelSize:"
|
|
||||||
" %" B_PRIx32 " address + size : %" B_PRIx32 "\n",
|
|
||||||
(uint32)address, (uint32)KERNEL_LOAD_BASE,
|
|
||||||
(uint32)KERNEL_LOAD_BASE + kMaxKernelSize,
|
|
||||||
(uint32)(address + size)));
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
for (uint32 i = 0; i < size; i++) {
|
|
||||||
map_page(address, get_next_physical_page(B_PAGE_SIZE),
|
|
||||||
kDefaultPageFlags);
|
|
||||||
address += B_PAGE_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return virtualAddress;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *address = (void *)sNextVirtualAddress;
|
|
||||||
|
|
||||||
for (uint32 i = 0; i < size; i++) {
|
|
||||||
map_page(get_next_virtual_page(B_PAGE_SIZE),
|
|
||||||
get_next_physical_page(B_PAGE_SIZE), kDefaultPageFlags);
|
|
||||||
}
|
|
||||||
|
|
||||||
return address;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*! This will unmap the allocated chunk of memory from the virtual
|
|
||||||
address space. It might not actually free memory (as its implementation
|
|
||||||
is very simple), but it might.
|
|
||||||
*/
|
|
||||||
extern "C" void
|
|
||||||
mmu_free(void *virtualAddress, size_t size)
|
|
||||||
{
|
|
||||||
TRACE(("mmu_free(virtualAddress = %p, size: %ld)\n", virtualAddress, size));
|
|
||||||
|
|
||||||
addr_t address = (addr_t)virtualAddress;
|
|
||||||
addr_t pageOffset = address % B_PAGE_SIZE;
|
|
||||||
address -= pageOffset;
|
|
||||||
size = (size + pageOffset + B_PAGE_SIZE - 1) / B_PAGE_SIZE * B_PAGE_SIZE;
|
|
||||||
|
|
||||||
// is the address within the valid range?
|
|
||||||
if (address < KERNEL_LOAD_BASE || address + size > sNextVirtualAddress) {
|
|
||||||
panic("mmu_free: asked to unmap out of range region (%p, size %lx)\n",
|
|
||||||
(void *)address, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
// unmap all pages within the range
|
|
||||||
for (size_t i = 0; i < size; i += B_PAGE_SIZE) {
|
|
||||||
unmap_page(address);
|
|
||||||
address += B_PAGE_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (address == sNextVirtualAddress) {
|
|
||||||
// we can actually reuse the virtual address space
|
|
||||||
sNextVirtualAddress -= size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*! Sets up the final and kernel accessible GDT and IDT tables.
|
|
||||||
BIOS calls won't work any longer after this function has
|
|
||||||
been called.
|
|
||||||
*/
|
|
||||||
extern "C" void
|
|
||||||
mmu_init_for_kernel(void)
|
|
||||||
{
|
|
||||||
TRACE(("mmu_init_for_kernel\n"));
|
|
||||||
|
|
||||||
// store next available pagetable in our pagedir mapping, for
|
|
||||||
// the kernel to use in early vm setup
|
|
||||||
gKernelArgs.arch_args.next_pagetable = sNextPageTableAddress - (addr_t)sPageDirectory;
|
|
||||||
|
|
||||||
// save the memory we've physically allocated
|
|
||||||
insert_physical_allocated_range((addr_t)sPageDirectory, sNextPhysicalAddress - (addr_t)sPageDirectory);
|
|
||||||
|
|
||||||
// Save the memory we've virtually allocated (for the kernel and other
|
|
||||||
// stuff)
|
|
||||||
insert_virtual_allocated_range(KERNEL_LOAD_BASE, sNextVirtualAddress - KERNEL_LOAD_BASE);
|
|
||||||
|
|
||||||
#ifdef TRACE_MEMORY_MAP
|
|
||||||
{
|
|
||||||
uint32 i;
|
|
||||||
|
|
||||||
dprintf("phys memory ranges:\n");
|
|
||||||
for (i = 0; i < gKernelArgs.num_physical_memory_ranges; i++) {
|
|
||||||
dprintf(" base 0x%08" B_PRIx64 ", length 0x%08" B_PRIx64 "\n",
|
|
||||||
gKernelArgs.physical_memory_range[i].start,
|
|
||||||
gKernelArgs.physical_memory_range[i].size);
|
|
||||||
}
|
|
||||||
|
|
||||||
dprintf("allocated phys memory ranges:\n");
|
|
||||||
for (i = 0; i < gKernelArgs.num_physical_allocated_ranges; i++) {
|
|
||||||
dprintf(" base 0x%08" B_PRIx64 ", length 0x%08" B_PRIx64 "\n",
|
|
||||||
gKernelArgs.physical_allocated_range[i].start,
|
|
||||||
gKernelArgs.physical_allocated_range[i].size);
|
|
||||||
}
|
|
||||||
|
|
||||||
dprintf("allocated virt memory ranges:\n");
|
|
||||||
for (i = 0; i < gKernelArgs.num_virtual_allocated_ranges; i++) {
|
|
||||||
dprintf(" base 0x%08" B_PRIx64 ", length 0x%08" B_PRIx64 "\n",
|
|
||||||
gKernelArgs.virtual_allocated_range[i].start,
|
|
||||||
gKernelArgs.virtual_allocated_range[i].size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
extern "C" void
|
|
||||||
mmu_init(void* fdt)
|
|
||||||
{
|
|
||||||
TRACE(("mmu_init\n"));
|
|
||||||
|
|
||||||
// skip RAM check if already done (rPi)
|
|
||||||
if (gKernelArgs.num_physical_memory_ranges == 0) {
|
|
||||||
// get map of physical memory (fill in kernel_args structure)
|
|
||||||
|
|
||||||
if (fdt_map_memory_ranges(fdt, "/memory", true) != B_OK) {
|
|
||||||
panic("Error: could not find physical memory ranges from FDT!\n");
|
|
||||||
|
|
||||||
#ifdef SDRAM_BASE
|
|
||||||
dprintf("Defaulting to 32MB at %" B_PRIx64 "\n", (uint64)SDRAM_BASE);
|
|
||||||
// specify available physical memory, using 32MB for now, since our
|
|
||||||
// ARMv5 targets have very little by default.
|
|
||||||
uint64 total = 32 * 1024 * 1024;
|
|
||||||
insert_physical_memory_range(SDRAM_BASE, total);
|
|
||||||
#else
|
|
||||||
return /*B_ERROR*/;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// see if subpages are disabled
|
|
||||||
if (mmu_read_C1() & (1 << 23))
|
|
||||||
sSmallPageType = ARM_MMU_L2_TYPE_SMALLNEW;
|
|
||||||
|
|
||||||
mmu_write_C1(mmu_read_C1() & ~((1 << 29) | (1 << 28) | (1 << 0)));
|
|
||||||
// access flag disabled, TEX remap disabled, mmu disabled
|
|
||||||
|
|
||||||
// allocate page directory in memory after loader
|
|
||||||
sPageDirectory = (uint32 *)ROUNDUP((addr_t)&_end, 0x100000);
|
|
||||||
sNextPageTableAddress = (addr_t)sPageDirectory + ARM_MMU_L1_TABLE_SIZE;
|
|
||||||
sPageTableRegionEnd = (addr_t)sPageDirectory + 0x200000;
|
|
||||||
|
|
||||||
// Mark start for dynamic allocation
|
|
||||||
sNextPhysicalAddress = sPageTableRegionEnd;
|
|
||||||
// We are going to allocate early kernel stuff there, so the virtual address
|
|
||||||
// has to be in kernel space. Either put it right after the identity mapped
|
|
||||||
// RAM (if it happens to be in the 0x80000000 range), or at the start of
|
|
||||||
// the kernel address space otherwise.
|
|
||||||
sNextVirtualAddress = KERNEL_LOAD_BASE + kMaxKernelSize;
|
|
||||||
if (sPageTableRegionEnd > sNextVirtualAddress)
|
|
||||||
sNextVirtualAddress = sPageTableRegionEnd;
|
|
||||||
|
|
||||||
// mark allocated ranges, so they don't get overwritten
|
|
||||||
insert_physical_allocated_range((addr_t)&_start,
|
|
||||||
(addr_t)&_end - (addr_t)&_start);
|
|
||||||
insert_physical_allocated_range((addr_t)sPageDirectory, 0x200000);
|
|
||||||
|
|
||||||
init_page_directory(fdt);
|
|
||||||
|
|
||||||
// map in a kernel stack
|
|
||||||
gKernelArgs.cpu_kstack[0].size = KERNEL_STACK_SIZE
|
|
||||||
+ KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE;
|
|
||||||
gKernelArgs.cpu_kstack[0].start = (addr_t)mmu_allocate(NULL,
|
|
||||||
gKernelArgs.cpu_kstack[0].size);
|
|
||||||
|
|
||||||
TRACE(("kernel stack at 0x%" B_PRIx64 " to 0x%" B_PRIx64 "\n",
|
|
||||||
gKernelArgs.cpu_kstack[0].start,
|
|
||||||
gKernelArgs.cpu_kstack[0].start + gKernelArgs.cpu_kstack[0].size));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
|
||||||
|
|
||||||
|
|
||||||
extern "C" status_t
|
|
||||||
platform_allocate_region(void **_address, size_t size, uint8 protection,
|
|
||||||
bool /*exactAddress*/)
|
|
||||||
{
|
|
||||||
void *address = mmu_allocate(*_address, size);
|
|
||||||
if (address == NULL)
|
|
||||||
return B_NO_MEMORY;
|
|
||||||
|
|
||||||
*_address = address;
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
extern "C" status_t
|
|
||||||
platform_free_region(void *address, size_t size)
|
|
||||||
{
|
|
||||||
mmu_free(address, size);
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
platform_release_heap(struct stage2_args *args, void *base)
|
|
||||||
{
|
|
||||||
// It will be freed automatically, since it is in the
|
|
||||||
// identity mapped region, and not stored in the kernel's
|
|
||||||
// page tables.
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
platform_init_heap(struct stage2_args *args, void **_base, void **_top)
|
|
||||||
{
|
|
||||||
void *heap = mmu_allocate(NULL, args->heap_size);
|
|
||||||
if (heap == NULL)
|
|
||||||
return B_NO_MEMORY;
|
|
||||||
|
|
||||||
*_base = heap;
|
|
||||||
*_top = (void *)((int8 *)heap + args->heap_size);
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2011, François Revol <revol@free.fr>.
|
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <arch/arm/arch_cpu.h>
|
|
||||||
|
|
||||||
#include <asm_defs.h>
|
|
||||||
|
|
||||||
|
|
||||||
.text
|
|
||||||
|
|
||||||
/* status_t arch_start_kernel(struct kernel_args *kernelArgs,
|
|
||||||
addr_t kernelEntry, addr_t kernelStackTop);
|
|
||||||
|
|
||||||
r0 - kernelArgs
|
|
||||||
r1 - kernelEntry
|
|
||||||
r2 - kernelStackTop
|
|
||||||
*/
|
|
||||||
FUNCTION(arch_start_kernel):
|
|
||||||
|
|
||||||
// set the kernel stack
|
|
||||||
mov sp,r2
|
|
||||||
|
|
||||||
// set up kernel _start args
|
|
||||||
//mov r0,r0 // kernelArgs
|
|
||||||
mov r4,r1
|
|
||||||
mov r1,#0 // currentCPU=0
|
|
||||||
|
|
||||||
// call the kernel
|
|
||||||
mov pc,r4
|
|
||||||
|
|
||||||
// return
|
|
||||||
mov r0,#-1 // B_ERROR
|
|
||||||
mov pc,lr
|
|
||||||
|
|
||||||
FUNCTION_END(arch_start_kernel)
|
|
||||||
|
|
||||||
@@ -1,94 +0,0 @@
|
|||||||
#include <arch/arm/arch_cpu.h>
|
|
||||||
|
|
||||||
#include <asm_defs.h>
|
|
||||||
|
|
||||||
.text
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Entry points to the loader that U-Boot passes control to.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* called as standalone (raw binary)
|
|
||||||
* *MUST* be first symbol
|
|
||||||
*/
|
|
||||||
SYMBOL(_start_raw):
|
|
||||||
/*
|
|
||||||
* ELF entry
|
|
||||||
*/
|
|
||||||
SYMBOL(_start):
|
|
||||||
mov r4,#0
|
|
||||||
b _start_common
|
|
||||||
SYMBOL_END(_start_raw)
|
|
||||||
SYMBOL_END(_start)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* called from bootm with netbsd loader compatible args
|
|
||||||
*/
|
|
||||||
SYMBOL(_start_netbsd):
|
|
||||||
mov r4,#1
|
|
||||||
b _start_common
|
|
||||||
SYMBOL_END(_start_netbsd)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* called from bootm with linux loader compatible args
|
|
||||||
*/
|
|
||||||
SYMBOL(_start_linux):
|
|
||||||
mov r4,#2
|
|
||||||
b _start_common
|
|
||||||
SYMBOL_END(_start_linux)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
SYMBOL(_start_common):
|
|
||||||
strb r4,gUBootOS
|
|
||||||
str r8,gUBootGlobalData
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Turn off interrupts and make sure we are in SVC mode
|
|
||||||
*/
|
|
||||||
|
|
||||||
mrs r4, cpsr
|
|
||||||
bic r4, r4, #0x1f
|
|
||||||
orr r4, r4, #0xd3
|
|
||||||
msr cpsr, r4
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Turn off MMU and data cache if necessary.
|
|
||||||
* WARNING: assumes we are running with a 1-1 mapping if MMU is enabled.
|
|
||||||
*/
|
|
||||||
mrc p15, 0, r4, c1, c0, 0
|
|
||||||
bic r4, r4, #0x0000000f // WCAM bits
|
|
||||||
bic r4, r4, #0x00000300 // RS bits
|
|
||||||
mcr p15, 0, r4, c1, c0, 0
|
|
||||||
mov r4, #0
|
|
||||||
mov r4, r4
|
|
||||||
mov r4, r4
|
|
||||||
|
|
||||||
ldr sp,=__stack_top
|
|
||||||
ldrb r4,gUBootOS
|
|
||||||
cmp r4,#0
|
|
||||||
beq start_raw
|
|
||||||
cmp r4,#1
|
|
||||||
beq start_netbsd
|
|
||||||
cmp r4,#2
|
|
||||||
beq start_linux
|
|
||||||
mov pc,lr
|
|
||||||
SYMBOL_END(_start_common)
|
|
||||||
|
|
||||||
|
|
||||||
//XXX: doesn't seem to work
|
|
||||||
//.data
|
|
||||||
|
|
||||||
.global __stack_end, __stack_start
|
|
||||||
|
|
||||||
SYMBOL(gUBootGlobalData):
|
|
||||||
.long 0
|
|
||||||
SYMBOL_END(gUBootGlobalData)
|
|
||||||
SYMBOL(gUBootOS):
|
|
||||||
//XXX: bug? Using .byte makes the next asm symbol
|
|
||||||
// to be at the same address
|
|
||||||
// .byte 0
|
|
||||||
.long 0
|
|
||||||
SYMBOL_END(gUBootOS)
|
|
||||||
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
|
|
||||||
OUTPUT_ARCH(arm)
|
|
||||||
|
|
||||||
STACK_SIZE = 16384;
|
|
||||||
|
|
||||||
ENTRY(_start)
|
|
||||||
SECTIONS
|
|
||||||
{
|
|
||||||
. = BOOT_LOADER_BASE;
|
|
||||||
|
|
||||||
/* text/read-only data */
|
|
||||||
.text : { *(.text .gnu.linkonce.t.*) }
|
|
||||||
|
|
||||||
. = ALIGN(0x4);
|
|
||||||
__ctor_list = .;
|
|
||||||
.ctors : { *(.ctors) *(.init_array) }
|
|
||||||
__ctor_end = .;
|
|
||||||
|
|
||||||
.rodata : { *(.rodata .rodata.*) }
|
|
||||||
|
|
||||||
/* writable data */
|
|
||||||
. = ALIGN(0x1000);
|
|
||||||
__data_start = .;
|
|
||||||
.data : { *(.data .gnu.linkonce.d.*) }
|
|
||||||
|
|
||||||
/* exception unwinding - should really not be needed! */
|
|
||||||
__exidx_start = .;
|
|
||||||
.ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) }
|
|
||||||
__exidx_end = .;
|
|
||||||
|
|
||||||
/* uninitialized data (in same segment as writable data) */
|
|
||||||
__bss_start = .;
|
|
||||||
.bss : { *(.bss) }
|
|
||||||
__bss_end = .;
|
|
||||||
|
|
||||||
.stack : {
|
|
||||||
__stack_start = .;
|
|
||||||
. += STACK_SIZE;
|
|
||||||
. = ALIGN(0x8);
|
|
||||||
__stack_top = .;
|
|
||||||
}
|
|
||||||
|
|
||||||
. = ALIGN(0x1000);
|
|
||||||
_end = . ;
|
|
||||||
/* Stabs debugging sections. */
|
|
||||||
.stab 0 : { *(.stab) }
|
|
||||||
.stabstr 0 : { *(.stabstr) }
|
|
||||||
/* DWARF debug sections.
|
|
||||||
Symbols in the DWARF debugging sections are relative to the beginning
|
|
||||||
of the section so we begin them at 0. */
|
|
||||||
/* DWARF 1 */
|
|
||||||
.debug 0 : { *(.debug) }
|
|
||||||
.line 0 : { *(.line) }
|
|
||||||
/* GNU DWARF 1 extensions */
|
|
||||||
.debug_srcinfo 0 : { *(.debug_srcinfo) }
|
|
||||||
.debug_sfnames 0 : { *(.debug_sfnames) }
|
|
||||||
/* DWARF 1.1 and DWARF 2 */
|
|
||||||
.debug_aranges 0 : { *(.debug_aranges) }
|
|
||||||
.debug_pubnames 0 : { *(.debug_pubnames) }
|
|
||||||
/* DWARF 2 */
|
|
||||||
.debug_info 0 : { *(.debug_info) }
|
|
||||||
.debug_abbrev 0 : { *(.debug_abbrev) }
|
|
||||||
.debug_line 0 : { *(.debug_line) }
|
|
||||||
.debug_frame 0 : { *(.debug_frame) }
|
|
||||||
.debug_str 0 : { *(.debug_str) }
|
|
||||||
.debug_loc 0 : { *(.debug_loc) }
|
|
||||||
.debug_macinfo 0 : { *(.debug_macinfo) }
|
|
||||||
/* SGI/MIPS DWARF 2 extensions */
|
|
||||||
.debug_weaknames 0 : { *(.debug_weaknames) }
|
|
||||||
.debug_funcnames 0 : { *(.debug_funcnames) }
|
|
||||||
.debug_typenames 0 : { *(.debug_typenames) }
|
|
||||||
.debug_varnames 0 : { *(.debug_varnames) }
|
|
||||||
/* These must appear regardless of . */
|
|
||||||
|
|
||||||
/* Strip unnecessary stuff */
|
|
||||||
/* /DISCARD/ : { *(.comment .note .eh_frame .dtors .stab .stabstr .debug*) }*/
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user