diff --git a/repos/base-foc/config/rpi2.kernel b/repos/base-foc/config/rpi2.kernel new file mode 100644 index 000000000..935ce9d6f --- /dev/null +++ b/repos/base-foc/config/rpi2.kernel @@ -0,0 +1,103 @@ +# +# Automatically generated file; DO NOT EDIT. +# Fiasco configuration +# +CONFIG_HAS_FPU_OPTION=y +CONFIG_HAS_VIRT_OBJ_SPACE_OPTION=y +CONFIG_HAS_SERIAL_OPTION=y +CONFIG_HAS_JDB_GZIP_OPTION=y +CONFIG_HAS_MP_OPTION=y + +# +# Target configuration +# +# CONFIG_IA32 is not set +# CONFIG_AMD64 is not set +CONFIG_ARM=y +# CONFIG_MIPS is not set +# CONFIG_PF_INTEGRATOR is not set +# CONFIG_PF_REALVIEW is not set +# CONFIG_PF_SUNXI is not set +CONFIG_PF_BCM283X=y +# CONFIG_PF_SA1100 is not set +# CONFIG_PF_XSCALE is not set +# CONFIG_PF_ARMADA38X is not set +# CONFIG_PF_KIRKWOOD is not set +# CONFIG_PF_TEGRA is not set +# CONFIG_PF_LAYERSCAPE is not set +# CONFIG_PF_IMX is not set +# CONFIG_PF_ARM_VIRT is not set +# CONFIG_PF_RCAR3 is not set +# CONFIG_PF_EXYNOS is not set +# CONFIG_PF_S3C2410 is not set +# CONFIG_PF_OMAP is not set +# CONFIG_PF_ZYNQ is not set +# CONFIG_PF_ZYNQMP is not set +CONFIG_BSP_NAME="bcm283x" +CONFIG_CAN_ARM_CPU_CORTEX_A7=y +CONFIG_ARM_V7=y +CONFIG_ARM_V6PLUS=y +CONFIG_ARM_V7PLUS=y +# CONFIG_PF_BCM283X_RPI1 is not set +CONFIG_PF_BCM283X_RPI2=y +# CONFIG_PF_BCM283X_RPI3 is not set +CONFIG_ABI_VF=y +CONFIG_ARM_CORTEX_A7=y +CONFIG_FPU=y +# CONFIG_ARM_ALIGNMENT_CHECK is not set +CONFIG_ARM_EM_STD=y +# CONFIG_ARM_EM_NS is not set +# CONFIG_ARM_EM_TZ is not set +# CONFIG_ARM_SMC_USER is not set +# CONFIG_ARM_ENABLE_SWP is not set +# CONFIG_ARM_LPAE is not set +CONFIG_ARM_CPU_ERRATA=y + +# +# Kernel options +# +CONFIG_MP=y +CONFIG_MP_MAX_CPUS=4 +CONFIG_CONTEXT_4K=y +CONFIG_FINE_GRAINED_CPUTIME=y +CONFIG_SCHED_FIXED_PRIO=y +CONFIG_VIRT_OBJ_SPACE=y + +# +# Debugging +# +CONFIG_INLINE=y +# CONFIG_NDEBUG is not set +CONFIG_NO_FRAME_PTR=y +# CONFIG_STACK_DEPTH is not set +# CONFIG_LIST_ALLOC_SANITY is not set +CONFIG_SERIAL=y +CONFIG_JDB=y +CONFIG_JDB_LOGGING=y +CONFIG_JDB_GZIP=y +# CONFIG_JDB_ACCOUNTING is not set +# CONFIG_WARN_NONE is not set +CONFIG_WARN_WARNING=y +# CONFIG_WARN_ANY is not set + +# +# ARM debugging options +# +# CONFIG_VMEM_ALLOC_TEST is not set +# CONFIG_DEBUG_KERNEL_PAGE_FAULTS is not set + +# +# Compiling +# +CONFIG_CC="gcc" +CONFIG_CXX="g++" +CONFIG_HOST_CC="gcc" +CONFIG_HOST_CXX="g++" +# CONFIG_MAINTAINER_MODE is not set +CONFIG_LABEL="" +# CONFIG_EXPERIMENTAL is not set +CONFIG_PERF_CNT=y +CONFIG_BIT32=y +CONFIG_WARN_LEVEL=1 +CONFIG_XARCH="arm" +CONFIG_ABI="vf" diff --git a/repos/base-foc/config/rpi2.user b/repos/base-foc/config/rpi2.user new file mode 100644 index 000000000..5d37049fd --- /dev/null +++ b/repos/base-foc/config/rpi2.user @@ -0,0 +1,90 @@ +# +# Automatically generated file; DO NOT EDIT. +# L4Re Configuration +# +CONFIG_ARCH_ENABLE_STACK_PROTECTOR=y +# CONFIG_BUILD_ARCH_amd64 is not set +CONFIG_BUILD_ARCH_arm=y +# CONFIG_BUILD_ARCH_arm64 is not set +# CONFIG_BUILD_ARCH_mips is not set +# CONFIG_BUILD_ARCH_ppc32 is not set +# CONFIG_BUILD_ARCH_sparc is not set +# CONFIG_BUILD_ARCH_x86 is not set +CONFIG_BUILD_ARCH="arm" +CONFIG_BUILD_ABI_l4f=y +CONFIG_BUILD_ABI="l4f" +# CONFIG_CPU_ARM_ARMV4 is not set +# CONFIG_CPU_ARM_ARMV4T is not set +# CONFIG_CPU_ARM_ARMV5 is not set +# CONFIG_CPU_ARM_ARMV5T is not set +# CONFIG_CPU_ARM_ARMV5TE is not set +# CONFIG_CPU_ARM_ARMV6 is not set +# CONFIG_CPU_ARM_ARMV6T2 is not set +# CONFIG_CPU_ARM_ARMV6ZK is not set +CONFIG_CPU_ARM_ARMV7A=y +CONFIG_CPU="armv7a" +CONFIG_CPU_ARMV6KPLUS=y +CONFIG_CPU_ARMV6PLUS=y +# CONFIG_PLATFORM_TYPE_wand_quad is not set +# CONFIG_PLATFORM_TYPE_bb_x15 is not set +CONFIG_PLATFORM_TYPE_rpi2=y +# CONFIG_PLATFORM_TYPE_sabre_lite is not set +# CONFIG_PLATFORM_TYPE_imx6 is not set +# CONFIG_PLATFORM_TYPE_zedboard is not set +# CONFIG_PLATFORM_TYPE_imx35 is not set +# CONFIG_PLATFORM_TYPE_rv_pbx is not set +# CONFIG_PLATFORM_TYPE_rv is not set +# CONFIG_PLATFORM_TYPE_kirkwood is not set +# CONFIG_PLATFORM_TYPE_pandaboard is not set +# CONFIG_PLATFORM_TYPE_arm_virt is not set +# CONFIG_PLATFORM_TYPE_tegra2 is not set +# CONFIG_PLATFORM_TYPE_imx7 is not set +# CONFIG_PLATFORM_TYPE_exynos4 is not set +# CONFIG_PLATFORM_TYPE_cubieboard2 is not set +# CONFIG_PLATFORM_TYPE_omap3_am33xx is not set +# CONFIG_PLATFORM_TYPE_ls1012afrdm is not set +# CONFIG_PLATFORM_TYPE_rpi_b is not set +# CONFIG_PLATFORM_TYPE_rv_vexpress_a15 is not set +# CONFIG_PLATFORM_TYPE_imx51 is not set +# CONFIG_PLATFORM_TYPE_ls1021atwr is not set +# CONFIG_PLATFORM_TYPE_tegra3 is not set +# CONFIG_PLATFORM_TYPE_imx28 is not set +# CONFIG_PLATFORM_TYPE_omap3evm is not set +# CONFIG_PLATFORM_TYPE_exynos5 is not set +# CONFIG_PLATFORM_TYPE_rcar3_m3 is not set +# CONFIG_PLATFORM_TYPE_parallella is not set +# CONFIG_PLATFORM_TYPE_zynqmp is not set +# CONFIG_PLATFORM_TYPE_beagleboard is not set +# CONFIG_PLATFORM_TYPE_imx21 is not set +# CONFIG_PLATFORM_TYPE_imx6ul is not set +# CONFIG_PLATFORM_TYPE_armada38x is not set +# CONFIG_PLATFORM_TYPE_omap5 is not set +# CONFIG_PLATFORM_TYPE_rv_vexpress is not set +# CONFIG_PLATFORM_TYPE_rpi_a is not set +# CONFIG_PLATFORM_TYPE_integrator is not set +# CONFIG_PLATFORM_TYPE_custom is not set +CONFIG_PLATFORM_TYPE="rpi2" +# CONFIG_USE_DROPS_STDDIR is not set +# CONFIG_USE_DICE is not set +CONFIG_DROPS_STDDIR="/path/to/l4re" +CONFIG_DROPS_INSTDIR="/path/to/l4re" +CONFIG_BID_COLORED_PHASES=y + +# +# Building +# +CONFIG_YACC="yacc" +CONFIG_LEX="flex" +CONFIG_CTAGS="ctags" +CONFIG_ETAGS="etags" +CONFIG_HAVE_LDSO=y +CONFIG_INT_CPP_NAME_SWITCH=y +CONFIG_INT_LD_NAME_SWITCH=y +# CONFIG_BID_STRIP_PROGS is not set +# CONFIG_BID_GCC_OMIT_FP is not set +CONFIG_BID_GCC_ENABLE_STACK_PROTECTOR=y +# CONFIG_BID_GCC_STACK_PROTECTOR_ALL is not set +CONFIG_BID_GCC_STACK_PROTECTOR=y +# CONFIG_BID_BUILD_DOC is not set +# CONFIG_RELEASE_MODE is not set +CONFIG_MAKECONFS_ADD="" diff --git a/repos/base-foc/lib/mk/spec/rpi2/kernel-foc.mk b/repos/base-foc/lib/mk/spec/rpi2/kernel-foc.mk new file mode 100644 index 000000000..4386d2649 --- /dev/null +++ b/repos/base-foc/lib/mk/spec/rpi2/kernel-foc.mk @@ -0,0 +1,3 @@ +KERNEL_CONFIG := $(REP_DIR)/config/rpi2.kernel + +include $(REP_DIR)/lib/mk/kernel-foc.inc diff --git a/repos/base-foc/lib/mk/spec/rpi2/syscall-foc.mk b/repos/base-foc/lib/mk/spec/rpi2/syscall-foc.mk new file mode 100644 index 000000000..0ddcd441a --- /dev/null +++ b/repos/base-foc/lib/mk/spec/rpi2/syscall-foc.mk @@ -0,0 +1,5 @@ +L4_CONFIG := $(call select_from_repositories,config/rpi2.user) + +L4_BIN_DIR := $(LIB_CACHE_DIR)/syscall-foc/build/bin/arm_armv7a + +include $(REP_DIR)/lib/mk/spec/arm/syscall-foc.inc diff --git a/repos/base-foc/ports/foc.hash b/repos/base-foc/ports/foc.hash index 6450a5f59..7fd52c44e 100644 --- a/repos/base-foc/ports/foc.hash +++ b/repos/base-foc/ports/foc.hash @@ -1 +1 @@ -f4faf7d7b48797f7938d5bf85ed14e5336ac14b6 +9403f0e7a6b3369796b877391f51969dc59ae3e8 diff --git a/repos/base-foc/ports/foc.port b/repos/base-foc/ports/foc.port index 8fb64a44b..b2d1a273a 100644 --- a/repos/base-foc/ports/foc.port +++ b/repos/base-foc/ports/foc.port @@ -2,5 +2,5 @@ LICENSE := GPLv2 VERSION := git DOWNLOADS := foc.git URL(foc) := https://git.mousetrap.xyz/alex/foc.git -REV(foc) := a01968f492dc3872ae0267eabc1845ea5a08dc99 +REV(foc) := 1d4cf94b59a9a6fe83b0d6a0d61b92736dcf75f2 DIR(foc) := src/kernel/foc diff --git a/repos/base/include/drivers/defs/rpi2.h b/repos/base/include/drivers/defs/rpi2.h new file mode 100644 index 000000000..10d6d90e2 --- /dev/null +++ b/repos/base/include/drivers/defs/rpi2.h @@ -0,0 +1,75 @@ +/* + * \brief MMIO and IRQ definitions for the Raspberry Pi + * \author Norman Feske + * \date 2013-04-05 + */ + +/* + * Copyright (C) 2013-2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _INCLUDE__DRIVERS__DEFS__RPI_H_ +#define _INCLUDE__DRIVERS__DEFS__RPI_H_ + +/* Genode includes */ +#include + +namespace Rpi { + enum { + RAM_0_BASE = 0x00000000, + RAM_0_SIZE = 0x10000000, /* XXX ? */ + + MMIO_0_BASE = 0x3f000000, + MMIO_0_SIZE = 0x02000000, + + /* + * IRQ numbers 0..7 refer to the basic IRQs. + * IRQ numbers 8..39 refer to GPU IRQs 0..31. + * IRQ numbers 40..71 refer to GPU IRQs 32..63. + */ + GPU_IRQ_BASE = 8, + + SYSTEM_TIMER_IRQ = GPU_IRQ_BASE + 1, + SYSTEM_TIMER_MMIO_BASE = 0x3f003000, + SYSTEM_TIMER_MMIO_SIZE = 0x1000, + SYSTEM_TIMER_CLOCK = 1000000, + + PL011_0_IRQ = 57, + PL011_0_MMIO_BASE = 0x3f201000, + PL011_0_MMIO_SIZE = 0x1000, + PL011_0_CLOCK = 3000000, + + IRQ_CONTROLLER_BASE = 0x3f00b200, + IRQ_CONTROLLER_SIZE = 0x100, + + GPIO_CONTROLLER_BASE = 0x3f200000, + GPIO_CONTROLLER_SIZE = 0x1000, + + USB_DWC_OTG_BASE = 0x3f980000, + USB_DWC_OTG_SIZE = 0x20000, + + /* timer */ + TIMER_IRQ = 0, + + /* USB host controller */ + DWC_IRQ = 17, + + /* CPU cache */ + CACHE_LINE_SIZE_LOG2 = 5, + + /* SD card */ + SDHCI_BASE = MMIO_0_BASE + 0x300000, + SDHCI_SIZE = 0x100, + SDHCI_IRQ = 62, + }; + + enum Videocore_cache_policy { NON_COHERENT = 0, + COHERENT = 1, + L2_ONLY = 2, + UNCACHED = 3 }; +}; + +#endif /* _INCLUDE__DRIVERS__DEFS__RPI_H_ */ diff --git a/repos/base/mk/spec/rpi2.mk b/repos/base/mk/spec/rpi2.mk new file mode 100644 index 000000000..2ca43d988 --- /dev/null +++ b/repos/base/mk/spec/rpi2.mk @@ -0,0 +1,5 @@ +SPECS += arm_v7a usb gpio + +REP_INC_DIR += include/spec/rpi2 + +include $(BASE_DIR)/mk/spec/arm_v7a.mk diff --git a/repos/base/run/platform_drv.inc b/repos/base/run/platform_drv.inc index e5ad96607..a39e2da5c 100644 --- a/repos/base/run/platform_drv.inc +++ b/repos/base/run/platform_drv.inc @@ -1,3 +1,8 @@ +proc is_platform_rpi {} { + return [expr [have_spec rpi] \ + || [have_spec rpi2]] +} + proc have_platform_drv {} { if {[have_spec linux]} { return 0 @@ -5,7 +10,7 @@ proc have_platform_drv {} { return [expr [have_spec arndale] \ || [have_spec imx53] \ - || [have_spec rpi] \ + || [is_platform_rpi] \ || [have_spec odroid_x2] \ || [have_spec x86]] } @@ -35,7 +40,7 @@ proc need_usb_hid { } { # proc nic_drv_binary { } { if {[have_spec linux]} { return linux_nic_drv } - if {[have_spec omap4] || [have_spec arndale] || [have_spec rpi]} { return usb_drv } + if {[have_spec omap4] || [have_spec arndale] || [is_platform_rpi]} { return usb_drv } if {!([have_spec imx53] || [have_spec riscv] || [have_spec odroid_xu])} { return nic_drv } return no_nic_drv_available } @@ -190,7 +195,7 @@ proc platform_drv_config {} { append_if [have_spec acpi] drv_config { } - append_if [have_spec rpi] drv_config { + append_if [is_platform_rpi] drv_config { } append drv_config { diff --git a/repos/dde_linux/lib/mk/spec/rpi2/usb.mk b/repos/dde_linux/lib/mk/spec/rpi2/usb.mk new file mode 100644 index 000000000..fcbfbbf8d --- /dev/null +++ b/repos/dde_linux/lib/mk/spec/rpi2/usb.mk @@ -0,0 +1,51 @@ +SRC_C += \ + usb/host/dwc_otg/dwc_otg/dwc_otg_adp.c \ + usb/host/dwc_otg/dwc_otg/dwc_otg_attr.c \ + usb/host/dwc_otg/dwc_otg/dwc_otg_cfi.c \ + usb/host/dwc_otg/dwc_otg/dwc_otg_cil.c \ + usb/host/dwc_otg/dwc_otg/dwc_otg_cil_intr.c \ + usb/host/dwc_otg/dwc_otg/dwc_otg_driver.c \ + usb/host/dwc_otg/dwc_otg/dwc_otg_hcd.c \ + usb/host/dwc_otg/dwc_otg/dwc_otg_hcd_ddma.c \ + usb/host/dwc_otg/dwc_otg/dwc_otg_hcd_intr.c \ + usb/host/dwc_otg/dwc_otg/dwc_otg_hcd_linux.c \ + usb/host/dwc_otg/dwc_otg/dwc_otg_hcd_queue.c + +SRC_C += \ + usb/host/dwc_otg/dwc_common_port/dwc_cc.c \ + usb/host/dwc_otg/dwc_common_port/dwc_common_linux.c \ + usb/host/dwc_otg/dwc_common_port/dwc_crypto.c \ + usb/host/dwc_otg/dwc_common_port/dwc_dh.c \ + usb/host/dwc_otg/dwc_common_port/dwc_mem.c \ + usb/host/dwc_otg/dwc_common_port/dwc_modpow.c \ + usb/host/dwc_otg/dwc_common_port/dwc_notifier.c + +SRC_C += net/usb/usbnet.c net/usb/smsc95xx.c + +include $(REP_DIR)/lib/mk/spec/arm_v7/usb.inc + +CC_OPT += -DDWC_LINUX -DPLATFORM_INTERFACE + +# needed for 'ehci-hcd.c', which we don't use on the rpi, but it is still +# part of the generic usb USB driver +CC_OPT += -DCONFIG_USB_EHCI_PCI=1 + +# for 'dwc_otg_hcd_linux.c' for enabling the FIQ, which we don't use anyway +CC_OPT += -DINTERRUPT_VC_USB=9 + +# for 'dwc_otg_driver.c' for preventing calls to set_irq_type +CC_OPT += -DIRQF_TRIGGER_LOW=1 + +INC_DIR += $(LX_CONTRIB_DIR)/drivers/usb/host/dwc_otg/dwc_common_port \ + $(LX_CONTRIB_DIR)/drivers/usb/host/dwc_otg/dwc_otg +SRC_CC += platform.cc + +vpath platform.cc $(LIB_DIR)/spec/rpi2 +vpath %.c $(LX_CONTRIB_DIR)/drivers/net/usb + +# enable C++11 support +CC_CXX_OPT += -std=gnu++11 + +LIBS += rpi_usb + +CC_CXX_WARN_STRICT = diff --git a/repos/dde_linux/lib/mk/usb.inc b/repos/dde_linux/lib/mk/usb.inc index 98a6069f1..00e339b46 100644 --- a/repos/dde_linux/lib/mk/usb.inc +++ b/repos/dde_linux/lib/mk/usb.inc @@ -22,6 +22,10 @@ CC_OPT += -DCONFIG_USB_DEVICEFS -DCONFIG_HOTPLUG -DDEBUG -DCONFIG_USB_PHY=1 \ -DCONFIG_GENERIC_PHY=0 -DCONFIG_USB_OTG_WHITELIST=0 \ -DCONFIG_USB_OTG=0 -DCONFIG_USB_NET_RNDIS_HOST=1 +ifneq (,$(findstring rpi2,$(SPECS))) + CC_OPT += -DPLATFORM_RPI2 +endif + CC_WARN = -Wall -Wno-unused-variable -Wno-uninitialized \ -Wno-unused-function -Wno-overflow diff --git a/repos/dde_linux/src/lib/usb/lx_emul.cc b/repos/dde_linux/src/lib/usb/lx_emul.cc index 449924c92..cdd7b5c3f 100644 --- a/repos/dde_linux/src/lib/usb/lx_emul.cc +++ b/repos/dde_linux/src/lib/usb/lx_emul.cc @@ -595,6 +595,10 @@ void *dma_alloc_coherent(struct device *, size_t size, dma_addr_t *dma, gfp_t) if (!addr) return 0; + #if defined(PLATFORM_RPI2) + *dma = (dma_addr_t) ((u32) dma | (u32) 0xc0000000); + #endif + lx_log(DEBUG_DMA, "DMA pool alloc addr: %p size %zx align: %d, phys: %lx", addr, size, PAGE_SHIFT, *dma); return addr; @@ -623,6 +627,10 @@ dma_addr_t dma_map_single_attrs(struct device *dev, void *ptr, Genode::error("translation virt->phys ", ptr, "->", Genode::Hex(phys), "failed, return ip ", __builtin_return_address(0)); + #if defined(PLATFORM_RPI2) + phys = (dma_addr_t) ((u32) phys | (u32) 0xc0000000); + #endif + lx_log(DEBUG_DMA, "virt: %p phys: %lx", ptr, phys); return phys; } diff --git a/repos/dde_linux/src/lib/usb/spec/rpi2/platform.cc b/repos/dde_linux/src/lib/usb/spec/rpi2/platform.cc new file mode 100644 index 000000000..8c01beb53 --- /dev/null +++ b/repos/dde_linux/src/lib/usb/spec/rpi2/platform.cc @@ -0,0 +1,199 @@ +/* + * \brief USB initialization for Raspberry Pi + * \author Norman Feske + * \date 2013-09-11 + */ + +/* + * Copyright (C) 2013-2017 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +/* Genode includes */ +#include +#include +#include + + +/* emulation */ +#include +#include +#include + +/* dwc-otg */ +#define new new_ +#include +#undef new + +using namespace Genode; + +unsigned dwc_irq(); + + +/************************************************ + ** Resource info passed to the dwc_otg driver ** + ************************************************/ + +enum { + DWC_BASE = 0x3f980000, + DWC_SIZE = 0x20000, +}; + + +static resource _dwc_otg_resource[] = +{ + { DWC_BASE, DWC_BASE + DWC_SIZE - 1, "dwc_otg", IORESOURCE_MEM }, + { dwc_irq(), dwc_irq(), "dwc_otg-irq" /* name unused */, IORESOURCE_IRQ } +}; + + +/*************************************** + ** Supplement to lx_emul environment ** + ***************************************/ + +#if VERBOSE_LX_EMUL +#define TRACE lx_printf("\033[32m%s\033[0m called, not implemented\n", __PRETTY_FUNCTION__) +#else +#define TRACE +#endif + +#define DUMMY(retval, name) \ +extern "C" long name() { \ + lx_printf("\033[32m%s\033[0m called, not implemented, stop\n", #name); \ + bt(); \ + for (;;); \ + return retval; \ +} + +#define CHECKED_DUMMY(retval, name) \ +extern "C" long name() { \ + lx_printf("\033[32m%s\033[0m called, not implemented, ignored\n", #name); \ + bt(); \ + return retval; \ +} + +#define SILENT_DUMMY(retval, name) \ +extern "C" long name() { return retval; } + + +/********************* + ** linux/hardirq.h ** + *********************/ + +int in_irq() +{ + TRACE; + return 0; +} + + +/******************* + ** linux/delay.h ** + *******************/ + +unsigned long loops_per_jiffy = 1; + +/*********************************** + ** Dummies for unused PCD driver ** + ***********************************/ + +/* + * The PCD driver is used for driving the DWC-OTG device as gadget. The + * Raspberry Pi solely supports the use of the controller as host device. + * Hence, the PCD parts are not needed. + */ + +DUMMY(-1, dwc_otg_pcd_disconnect_us); +DUMMY(-1, dwc_otg_pcd_remote_wakeup); +DUMMY(-1, dwc_otg_pcd_get_rmwkup_enable); +DUMMY(-1, dwc_otg_pcd_initiate_srp); +DUMMY(-1, pcd_remove); +SILENT_DUMMY( 0, pcd_init); + + +/************************************************************************ + ** Prevent use of FIQ fix, need to resolve FIQ-related symbols anyway ** + ************************************************************************/ + +void local_fiq_disable() { } +void local_fiq_enable() { } +extern "C" void fiq_fsm_spin_lock(void *lock) { } +extern "C" void fiq_fsm_spin_unlock(void *lock) { } +int claim_fiq(struct fiq_handler *f) { return 0; } +void set_fiq_regs(struct pt_regs const *regs) { } +void set_fiq_handler(void *start, unsigned int length) { } +void enable_fiq() { } + +void __FIQ_Branch(unsigned long *regs) { TRACE; } + +extern "C" int fiq_fsm_too_late(struct fiq_state *st, int n) { TRACE; return 0; } +extern "C" void dwc_otg_fiq_nop(struct fiq_state *state) { TRACE; } +extern "C" void dwc_otg_fiq_fsm(struct fiq_state *state, int num_channels) { TRACE; } + +unsigned char _dwc_otg_fiq_stub, _dwc_otg_fiq_stub_end; + + +/*********************** + ** asm/dma_mapping.h ** + ***********************/ + +void *dma_to_virt(struct device *dev, dma_addr_t phys) +{ + return phys_to_virt(phys); +} + + +/******************* + ** linux/timer.h ** + *******************/ + +struct tvec_base { }; +struct tvec_base boot_tvec_bases; + + +/******************* + ** Init function ** + *******************/ + +extern "C" void module_dwc_otg_driver_init(); +extern "C" int module_usbnet_init(); +extern "C" int module_smsc95xx_driver_init(); + +void platform_hcd_init(Services *services) +{ + /* enable USB power */ + Platform::Connection platform; + platform.power_state(Platform::Session::POWER_USB_HCD, true); + + /* register network */ + if (services->nic) { + module_usbnet_init(); + module_smsc95xx_driver_init(); + } + + /* disable fiq optimization */ + fiq_enable = false; + fiq_fsm_enable = false; + + bool const verbose = false; + if (verbose) + g_dbg_lvl = DBG_HCD | DBG_CIL | DBG_HCD_URB; + + module_dwc_otg_driver_init(); + + /* setup host-controller platform device */ + platform_device *pdev = (platform_device *)kzalloc(sizeof(platform_device), 0); + pdev->name = (char *)"dwc_otg"; + pdev->id = 0; + pdev->num_resources = sizeof(_dwc_otg_resource)/sizeof(resource); + pdev->resource = _dwc_otg_resource; + + /* needed for DMA buffer allocation. See 'hcd_buffer_alloc' in 'buffer.c' */ + static u64 dma_mask = ~(u64)0; + pdev->dev.dma_mask = &dma_mask; + pdev->dev.coherent_dma_mask = ~0; + + platform_device_register(pdev); +} diff --git a/repos/libports/run/lwip.run b/repos/libports/run/lwip.run index 6126df4c5..9fbc5300e 100644 --- a/repos/libports/run/lwip.run +++ b/repos/libports/run/lwip.run @@ -20,7 +20,7 @@ # tun/tap proxy driver at os/src/drivers/nic/linux) # -set use_usb_driver [expr [have_spec omap4] || [have_spec arndale] || [have_spec rpi]] +set use_usb_driver [expr [have_spec omap4] || [have_spec arndale] || [have_spec rpi] || [have_spec rpi2]] set use_nic_driver [expr !$use_usb_driver && ![have_spec imx53] && ![have_spec odroid_xu] && ![have_spec linux]] if {[expr !$use_usb_driver && !$use_nic_driver]} { @@ -42,7 +42,7 @@ lappend_if $use_usb_driver build_components drivers/usb lappend_if [have_spec gpio] build_components drivers/gpio proc gpio_drv { } { if {[have_spec rpi] && [have_spec hw]} { return hw_gpio_drv } - if {[have_spec rpi] && [have_spec foc]} { return foc_gpio_drv } + if {([have_spec rpi] || [have_spec rpi2]) && [have_spec foc]} { return foc_gpio_drv } return gpio_drv } source ${genode_dir}/repos/base/run/platform_drv.inc diff --git a/repos/os/include/spec/rpi2/platform/framebuffer_info.h b/repos/os/include/spec/rpi2/platform/framebuffer_info.h new file mode 100644 index 000000000..eb4084d2c --- /dev/null +++ b/repos/os/include/spec/rpi2/platform/framebuffer_info.h @@ -0,0 +1,59 @@ +/* + * \brief Framebuffer info structure + * \author Norman Feske + * \date 2013-09-15 + */ + +/* + * Copyright (C) 2013-2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _PLATFORM__FRAMEBUFFER_INFO_H_ +#define _PLATFORM__FRAMEBUFFER_INFO_H_ + +#include + +namespace Platform { + using namespace Genode; + struct Framebuffer_info; +} + + +/** + * Structure used by the protocol between the Videocore GPU and the ARM CPU for + * setting up the framebuffer via the mbox. + */ +struct Platform::Framebuffer_info +{ + uint32_t phys_width; + uint32_t phys_height; + uint32_t virt_width; + uint32_t virt_height; + uint32_t pitch = 0; + uint32_t depth; + uint32_t x_offset = 0; + uint32_t y_offset = 0; + uint32_t addr = 0; + uint32_t size = 0; + + /** + * Default constructor needed to make the object transferable via RPC + */ + Framebuffer_info() + : + phys_width(0), phys_height(0), virt_width(0), virt_height(), + depth(0) + { } + + Framebuffer_info(uint32_t width, uint32_t height, uint32_t depth) + : + phys_width(width), phys_height(height), + virt_width(width), virt_height(height), + depth(depth) + { } +}; + +#endif /* _PLATFORM__FRAMEBUFFER_INFO_H_ */ diff --git a/repos/os/include/spec/rpi2/platform/property_message.h b/repos/os/include/spec/rpi2/platform/property_message.h new file mode 100644 index 000000000..9e529ebae --- /dev/null +++ b/repos/os/include/spec/rpi2/platform/property_message.h @@ -0,0 +1,226 @@ +/* + * \brief Marshalling of mbox messages for property channel + * \author Norman Feske + * \date 2013-09-15 + */ + +/* + * Copyright (C) 2013-2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _PLATFORM__PROPERTY_MESSAGE_H_ +#define _PLATFORM__PROPERTY_MESSAGE_H_ + +/* Genode includes */ +#include +#include + +/* board-specific includes */ +#include + +namespace Platform { + using namespace Genode; + struct Property_message; +} + + +/** + * Mailbox message buffer for the property channel + * + * This data structure is overlayed with memory shared with the VC. It + * contains a header, followed by a sequence of so-called command tags, wrapped + * up by a zero as an end marker. + */ +struct Platform::Property_message +{ + uint32_t buf_size = 0; + + enum Code { REQUEST = 0, + RESPONSE_SUCCESS = 0x80000000 }; + + Code code = REQUEST; + + /* + * Start of the buffer that contains a sequence of tags + */ + char buffer[0]; + + /* + * There must be no member variables after this point + */ + + /* + * Each tag consists of a header, a part with request arguments, and a + * part with responses. + */ + template + struct Tag + { + uint32_t const opcode; + + /** + * Size of tag buffer + */ + uint32_t const buf_size; + + /** + * Size of request part of the tag + * + * The value is never changed locally. Therefore, it is declared as + * const. However, it will be updated by the VC. So we declare it + * volatile, too. + */ + uint32_t volatile const len; + + char payload[0]; + + /** + * Utility for returning a response size of a tag type + * + * Depending on the presence of a 'TAG::Response' type, we need to + * return the actual size of the response (if the type is present) or + * 0. Both overloads are called with a compliant parameter 0. But only + * if 'T::Response' exists, the first overload is selected. + * + * SFINAE to the rescue! + */ + template + static size_t response_size(typename T::Response *) + { + return sizeof(typename T::Response); + } + + template + static size_t response_size(...) + { + return 0; + } + + template + static size_t request_size(typename T::Request *) + { + return sizeof(typename T::Request); + } + + template + static size_t request_size(...) + { + return 0; + } + + template + struct Placeable : T + { + template + Placeable(ARGS... args) : T(args...) { } + + inline void *operator new (__SIZE_TYPE__, void *ptr) { return ptr; } + }; + + template + void construct_request(typename T::Request *, ARGS... args) + { + new ((typename T::Request *)payload) + Placeable(args...); + } + + template + void construct_request(...) { } + + template + void construct_response(typename T::Response *) + { + new (payload) Placeable; + } + + template + void construct_response(...) { } + + static constexpr size_t payload_size() + { + return max(request_size(0), response_size(0)); + } + + template + Tag(REQUEST_ARGS... request_args) + : + opcode(TAG::opcode()), + buf_size(payload_size()), + len(request_size(0)) + { + /* + * The order is important. If we called 'construct_response' after + * 'construct_request', we would overwrite the request parameters + * with the default response. + */ + construct_response(0); + construct_request(0, request_args...); + } + + inline void *operator new (__SIZE_TYPE__, void *ptr) { return ptr; } + }; + + void reset() + { + buf_size = 0; + code = REQUEST; + } + + /** + * \return reference to tag in the message buffer + */ + template + typename POLICY::Response const &append(REQUEST_ARGS... request_args) + { + auto *tag = new (buffer + buf_size) Tag(request_args...); + + buf_size += sizeof(Tag) + Tag::payload_size(); + + return *(typename POLICY::Response *)tag->payload; + } + + template + void append_no_response(REQUEST_ARGS... request_args) + { + new (buffer + buf_size) Tag(request_args...); + + buf_size += sizeof(Tag) + Tag::payload_size(); + } + + void finalize() + { + /* append end tag */ + *(uint32_t *)(buffer + buf_size) = 0; + buf_size += sizeof(uint32_t); + } + + static unsigned channel() { return 8; } + + static Rpi::Videocore_cache_policy cache_policy() + { + return Rpi::NON_COHERENT; /* for channel 8 only */ + } + + void dump(char const *label) + { + unsigned const *buf = (unsigned *)this; + printf("%s message:\n", label); + for (unsigned i = 0;; i++) { + for (unsigned j = 0; j < 8; j++) { + unsigned const msg_word_idx = i*8 + j; + printf(" %08x", buf[msg_word_idx]); + if (msg_word_idx*sizeof(unsigned) < buf_size) + continue; + printf("\n"); + return; + } + } + } + + inline void *operator new (__SIZE_TYPE__, void *ptr) { return ptr; } +}; + +#endif /* _PLATFORM__PROPERTY_MESSAGE_H_ */ diff --git a/repos/os/include/spec/rpi2/platform_session/client.h b/repos/os/include/spec/rpi2/platform_session/client.h new file mode 100644 index 000000000..846126373 --- /dev/null +++ b/repos/os/include/spec/rpi2/platform_session/client.h @@ -0,0 +1,41 @@ +/* + * \brief Raspberry Pi specific platform session client side + * \author Norman Feske + * \date 2013-09-16 + */ + +/* + * Copyright (C) 2013-2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _INCLUDE__PLATFORM_SESSION__CLIENT_H_ +#define _INCLUDE__PLATFORM_SESSION__CLIENT_H_ + +#include +#include +#include + +namespace Platform { struct Client; } + +struct Platform::Client : Genode::Rpc_client +{ + explicit Client(Capability session) + : Genode::Rpc_client(session) { } + + void setup_framebuffer(Framebuffer_info &info) override { + call(info); } + + bool power_state(Power power) override { + return call(power); } + + void power_state(Power power, bool enable) override { + call(power, enable); } + + uint32_t clock_rate(Clock clock) { + return call(clock); } +}; + +#endif /* _INCLUDE__PLATFORM_SESSION__CLIENT_H_ */ diff --git a/repos/os/include/spec/rpi2/platform_session/platform_session.h b/repos/os/include/spec/rpi2/platform_session/platform_session.h new file mode 100644 index 000000000..17cc82554 --- /dev/null +++ b/repos/os/include/spec/rpi2/platform_session/platform_session.h @@ -0,0 +1,89 @@ +/* + * \brief Raspberry Pi specific platform session + * \author Norman Feske + * \date 2013-09-16 + */ + +/* + * Copyright (C) 2013-2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _INCLUDE__PLATFORM_SESSION__PLATFORM_SESSION_H_ +#define _INCLUDE__PLATFORM_SESSION__PLATFORM_SESSION_H_ + +#include +#include +#include +#include + +namespace Platform { + using namespace Genode; + struct Session; +} + + +struct Platform::Session : Genode::Session +{ + /** + * \noapi + */ + static const char *service_name() { return "Platform"; } + + enum { CAP_QUOTA = 2 }; + + /** + * Setup framebuffer + * + * The 'info' argument serves as both input and output parameter. As input, + * it describes the desired properties of the framebuffer. In return, the + * method delivers the values that were actually taken into effect. + */ + virtual void setup_framebuffer(Framebuffer_info &info) = 0; + + enum Power { + POWER_SDHCI = 0, + POWER_UART0 = 1, + POWER_UART1 = 2, + POWER_USB_HCD = 3, + POWER_I2C0 = 4, + POWER_I2C1 = 5, + POWER_I2C2 = 6, + POWER_SPI = 7, + POWER_CCP2TX = 8, + }; + + /** + * Request power state + */ + virtual bool power_state(Power) = 0; + + /** + * Set power state + */ + virtual void power_state(Power, bool enable) = 0; + + enum Clock { CLOCK_EMMC = 1 }; + + /** + * Request clock rate + */ + virtual uint32_t clock_rate(Clock) = 0; + + + /********************* + ** RPC declaration ** + *********************/ + + GENODE_RPC(Rpc_setup_framebuffer, void, setup_framebuffer, Framebuffer_info &); + GENODE_RPC(Rpc_get_power_state, bool, power_state, Power); + GENODE_RPC(Rpc_set_power_state, void, power_state, Power, bool); + GENODE_RPC(Rpc_get_clock_rate, uint32_t, clock_rate, Clock); + + GENODE_RPC_INTERFACE(Rpc_setup_framebuffer, Rpc_set_power_state, + Rpc_get_power_state, Rpc_get_clock_rate); +}; + +#endif /* _INCLUDE__PLATFORM_SESSION__PLATFORM_SESSION_H_ */ diff --git a/repos/os/src/drivers/gpio/spec/rpi2/driver.h b/repos/os/src/drivers/gpio/spec/rpi2/driver.h new file mode 100644 index 000000000..f5936fc65 --- /dev/null +++ b/repos/os/src/drivers/gpio/spec/rpi2/driver.h @@ -0,0 +1,208 @@ +/* + * \brief Gpio driver for the RaspberryPI + * \author Reinier Millo Sánchez + * \author Alexy Gallardo Segura + * \author Humberto Lopéz Leon + * \date 2015-07-23 + */ + +/* + * Copyright (C) 2012 Ksys Labs LLC + * Copyright (C) 2012-2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _DRIVERS__GPIO__SPEC__RPI__DRIVER_H_ +#define _DRIVERS__GPIO__SPEC__RPI__DRIVER_H_ + +/* Genode includes */ +#include +#include +#include +#include + +/* local includes */ +#include +#include + +static int verbose = 1; + +namespace Gpio { class Rpi_driver; } + +class Gpio::Rpi_driver : public Driver +{ + private: + + enum { MAX_PINS = 54 }; + + Reg _reg; + Genode::Irq_connection _irq; + Genode::Signal_handler _dispatcher; + Genode::Signal_context_capability _sig_cap[MAX_PINS]; + bool _irq_enabled[MAX_PINS]; + bool _async; + + void _handle() + { + _reg.for_each_gpio_status([&] (unsigned i, bool s) { + if (!s || !_irq_enabled[i] || !_sig_cap[i].valid()) { return; } + Genode::Signal_transmitter(_sig_cap[i]).submit(); + }); + } + + Rpi_driver(Genode::Env &env) + : + _reg(env, Rpi::GPIO_CONTROLLER_BASE, 0, Rpi::GPIO_CONTROLLER_SIZE), + _irq(env, IRQ), + _dispatcher(env.ep(), *this, &Rpi_driver::_handle), + _async(false) + { + _irq.sigh(_dispatcher); + _irq.ack_irq(); + } + + void _invalid_gpio(unsigned gpio) { + Genode::error("invalid GPIO pin number ", gpio); } + + public: + + void set_async_events(bool async) { _async = async; } + + void set_func(unsigned gpio, Reg::Function function) + { + if (verbose) + Genode::log("set_func: gpio=", gpio, " function=", (int)function); + + _reg.set_gpio_function(gpio, function); + } + + static Rpi_driver& factory(Genode::Env &env); + + + /****************************** + ** Driver interface ** + ******************************/ + + bool gpio_valid(unsigned gpio) { return gpio < MAX_PINS; } + + void direction(unsigned gpio, bool input) + { + if (!gpio_valid(gpio)) { _invalid_gpio(gpio); return; } + + if (verbose) + Genode::log("direction: gpio=", gpio, " input=", input); + + Reg::Function f = input ? Reg::FSEL_INPUT : Reg::FSEL_OUTPUT; + _reg.set_gpio_function(gpio, f); + } + + void write(unsigned gpio, bool level) + { + if (!gpio_valid(gpio)) { _invalid_gpio(gpio); return; } + + if (verbose) + Genode::log("write: gpio=", gpio, " level=", level); + + if (_reg.get_gpio_function(gpio)!=Reg::FSEL_OUTPUT) + warning("GPIO pin ", gpio, " is not configured for output"); + + if (level) + _reg.set_gpio_level(gpio); + else + _reg.clear_gpio_level(gpio); + } + + bool read(unsigned gpio) + { + if (!gpio_valid(gpio)) { _invalid_gpio(gpio); return 0; } + if(_reg.get_gpio_function(gpio) != Reg::FSEL_INPUT) + warning("GPIO pin ", gpio, " is not configured for input"); + + return _reg.get_gpio_level(gpio); + } + + void debounce_enable(unsigned, bool) { + Genode::warning("debounce_enable not supported!"); } + + void debounce_time(unsigned, unsigned long) { + Genode::warning("debounce_time not supported!"); } + + void falling_detect(unsigned gpio) + { + if (!gpio_valid(gpio)) { _invalid_gpio(gpio); return; } + + if (verbose) Genode::log("falling_detect: gpio=", gpio); + + if(_async) + _reg.set_gpio_async_falling_detect(gpio); + else + _reg.set_gpio_falling_detect(gpio); + } + + void rising_detect(unsigned gpio) + { + if (!gpio_valid(gpio)) { _invalid_gpio(gpio); return; } + + if (verbose) Genode::log("rising_detect: gpio=", gpio); + + if(_async) + _reg.set_gpio_async_rising_detect(gpio); + else + _reg.set_gpio_rising_detect(gpio); + } + + void high_detect(unsigned gpio) + { + if (!gpio_valid(gpio)) { _invalid_gpio(gpio); return; } + if (verbose) Genode::log("high_detect: gpio=", gpio); + + _reg.set_gpio_high_detect(gpio); + } + + void low_detect(unsigned gpio) + { + if (!gpio_valid(gpio)) { _invalid_gpio(gpio); return; } + if (verbose) Genode::log("low_detect: gpio=", gpio); + + _reg.set_gpio_low_detect(gpio); + } + + void irq_enable(unsigned gpio, bool enable) + { + if (!gpio_valid(gpio)) { _invalid_gpio(gpio); return; } + if (verbose) Genode::log("irq_enable: gpio=", gpio, " enable=", enable); + + _irq_enabled[gpio] = enable; + } + + void ack_irq(unsigned gpio) + { + if (!gpio_valid(gpio)) { _invalid_gpio(gpio); return; } + if (verbose) Genode::log("ack_irq: gpio=", gpio); + + _reg.clear_event(gpio); + _irq.ack_irq(); + } + + void register_signal(unsigned gpio, + Genode::Signal_context_capability cap) + { + if (!gpio_valid(gpio)) { _invalid_gpio(gpio); return; } + if (verbose) Genode::log("register_signal: gpio=", gpio); + + _sig_cap[gpio] = cap; + } + + void unregister_signal(unsigned gpio) + { + if (!gpio_valid(gpio)) { _invalid_gpio(gpio); return; } + if (verbose) Genode::log("unregister_signal: gpio=", gpio); + Genode::Signal_context_capability cap; + + _sig_cap[gpio] = cap; + } +}; + +#endif /* _DRIVERS__GPIO__SPEC__RPI__DRIVER_H_ */ diff --git a/repos/os/src/drivers/gpio/spec/rpi2/empty.cc b/repos/os/src/drivers/gpio/spec/rpi2/empty.cc new file mode 100644 index 000000000..066c1bf82 --- /dev/null +++ b/repos/os/src/drivers/gpio/spec/rpi2/empty.cc @@ -0,0 +1,3 @@ +/* + * Dummy compilation unit needed to link a valid target. + */ diff --git a/repos/os/src/drivers/gpio/spec/rpi2/foc/irq.h b/repos/os/src/drivers/gpio/spec/rpi2/foc/irq.h new file mode 100644 index 000000000..9a2774a6d --- /dev/null +++ b/repos/os/src/drivers/gpio/spec/rpi2/foc/irq.h @@ -0,0 +1,19 @@ +/* + * \brief GPIO interrupt number + * \author Reinier Millo Sánchez + * \date 2015-07-27 + */ + +/* + * Copyright (C) 2015-2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _DRIVERS__GPIO__SPEC__RPI__SPEC__FOC__IRQ_H_ +#define _DRIVERS__GPIO__SPEC__RPI__SPEC__FOC__IRQ_H_ + +namespace Gpio { enum { IRQ = 49 }; } + +#endif /* _DRIVERS__GPIO__SPEC__RPI__SPEC__FOC__IRQ_H_ */ diff --git a/repos/os/src/drivers/gpio/spec/rpi2/foc/target.mk b/repos/os/src/drivers/gpio/spec/rpi2/foc/target.mk new file mode 100644 index 000000000..6061abc6c --- /dev/null +++ b/repos/os/src/drivers/gpio/spec/rpi2/foc/target.mk @@ -0,0 +1,7 @@ +TARGET = foc_gpio_drv +REQUIRES = rpi2 +SRC_CC += main.cc +LIBS = base +INC_DIR += $(PRG_DIR) $(PRG_DIR)/.. + +vpath main.cc $(PRG_DIR)/.. diff --git a/repos/os/src/drivers/gpio/spec/rpi2/gpio.h b/repos/os/src/drivers/gpio/spec/rpi2/gpio.h new file mode 100644 index 000000000..af0e325e5 --- /dev/null +++ b/repos/os/src/drivers/gpio/spec/rpi2/gpio.h @@ -0,0 +1,242 @@ +/* + * \brief Gpio driver for the RaspberryPI + * \author Reinier Millo Sánchez + * \author Alexy Gallardo Segura + * \author Humberto Lopéz Leon + * \date 2015-07-23 + */ + +/* + * Copyright (C) 2012 Ksys Labs LLC + * Copyright (C) 2012-2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _DRIVERS__GPIO__SPEC__RPI__GPIO_H_ +#define _DRIVERS__GPIO__SPEC__RPI__GPIO_H_ + +/* Genode includes */ +#include +#include +#include +#include + +namespace Gpio { + + using namespace Genode; + + class Reg; +} + +class Gpio::Reg : Attached_io_mem_dataspace, Mmio +{ + private: + + /** + * GPIO Function Select Registers + */ + struct Gpfsel : Register_array <0x00,32,6,32> { + struct Sel0 : Bitfield <0,3> {}; + struct Sel1 : Bitfield <3,3> {}; + struct Sel2 : Bitfield <6,3> {}; + struct Sel3 : Bitfield <9,3> {}; + struct Sel4 : Bitfield <12,3> {}; + struct Sel5 : Bitfield <15,3> {}; + struct Sel6 : Bitfield <18,3> {}; + struct Sel7 : Bitfield <21,3> {}; + struct Sel8 : Bitfield <24,3> {}; + struct Sel9 : Bitfield <27,3> {}; + }; + + /** + * GPIO Pin Output Set Registers + */ + struct Gpset : Register_array <0x1c,32,64,1> {}; + + /** + * GPIO Pin Output Clear Registers + */ + struct Gpclr : Register_array <0x28,32,64,1> {}; + + /** + * GPIO Pin Level Registers + */ + struct Gplev : Register_array <0x34,32,64,1> {}; + + /** + * GPIO Pin Event Detect Status Registers + */ + struct Gppeds : Register_array <0x40,32,64,1> {}; + struct Gppeds_raw : Register <0x40,64> {}; + + /** + * GPIO Pin Rising Edge Detect Enable Registers + */ + struct Gpren : Register_array <0x4c,32,64,1> {}; + + /** + * GPIO Pin Falling Edge Detect Enable Registers + */ + struct Gpfen : Register_array <0x58,32,64,1> {}; + + /** + * GPIO Pin High Detect Enable Registers + */ + struct Gphen : Register_array <0x64,32,64,1> {}; + + /** + * GPIO Pin Low Detect Enable Registers + */ + struct Gplen : Register_array <0x70,32,64,1> {}; + + /** + * GPIO Pin Aync. Rising Edge Detect Registers + */ + struct Gparen : Register_array <0x7c,32,64,1> {}; + + /** + * GPIO Pin Async. Falling Edge Detect Registers + */ + struct Gpafen : Register_array <0x88,32,64,1> {}; + + /** + * GPIO Pin Pull-up/down Enable Registers + */ + struct Gppud : Register <0x94,32> {}; + + /** + * GPIO Pin Pull-up/down Enable Clock Registers + */ + struct Gppudclk : Register_array <0x98,32,64,1> {}; + + struct Timer_delayer : Timer::Connection, Mmio::Delayer + { + Timer_delayer(Genode::Env &env) : Timer::Connection(env) { } + + /** + * Implementation of 'Delayer' interface + */ + void usleep(unsigned us) { Timer::Connection::usleep(us); } + + } _delayer; + + template + void _set_gpio_det(unsigned gpio) + { + write(0, gpio); + write(0, gpio); + write(0, gpio); + write(0, gpio); + write(0, gpio); + write(1, gpio); + } + + public: + + Reg(Genode::Env &env, + addr_t base, off_t offset, size_t size) + : + Attached_io_mem_dataspace(env, base, size), + Mmio((addr_t)local_addr() + offset), + _delayer(env) + { } + + enum Function { + FSEL_INPUT = 0, + FSEL_OUTPUT = 1, + FSEL_ALT0 = 4, + FSEL_ALT1 = 5, + FSEL_ALT2 = 6, + FSEL_ALT3 = 7, + FSEL_ALT4 = 3, + FSEL_ALT5 = 2, + }; + + void set_gpio_function(unsigned gpio, Function function) + { + /* + * Set a pull-up internal resistor in the input pin to avoid + * electromagnetic radiation or static noise + */ + if (function == FSEL_INPUT) { + write(1); + _delayer.usleep(1); + write(1, gpio); + _delayer.usleep(1); + write(0); + write(0, gpio); + } + /* set the pin function */ + unsigned sel_id = gpio % 10; + unsigned reg_id = gpio / 10; + switch(sel_id){ + case 0: write(function, reg_id); break; + case 1: write(function, reg_id); break; + case 2: write(function, reg_id); break; + case 3: write(function, reg_id); break; + case 4: write(function, reg_id); break; + case 5: write(function, reg_id); break; + case 6: write(function, reg_id); break; + case 7: write(function, reg_id); break; + case 8: write(function, reg_id); break; + case 9: write(function, reg_id); break; + default:; + } + } + + unsigned get_gpio_function(unsigned gpio) + { + unsigned sel_id = gpio % 10; + unsigned reg_id = gpio / 10; + switch(sel_id){ + case 0: return read(reg_id); + case 1: return read(reg_id); + case 2: return read(reg_id); + case 3: return read(reg_id); + case 4: return read(reg_id); + case 5: return read(reg_id); + case 6: return read(reg_id); + case 7: return read(reg_id); + case 8: return read(reg_id); + case 9: return read(reg_id); + default: return 0; + } + } + + int get_gpio_level(unsigned gpio) { return read(gpio); } + void set_gpio_level(unsigned gpio) { write(1, gpio); } + void clear_gpio_level(unsigned gpio) { write(1, gpio); } + + void set_gpio_falling_detect(unsigned gpio) { + _set_gpio_det(gpio); } + + void set_gpio_rising_detect(unsigned gpio) { + _set_gpio_det(gpio); } + + void set_gpio_high_detect(unsigned gpio) { + _set_gpio_det(gpio); } + + void set_gpio_low_detect(unsigned gpio) { + _set_gpio_det(gpio); } + + void set_gpio_async_falling_detect(unsigned gpio) { + _set_gpio_det(gpio); } + + void set_gpio_async_rising_detect(unsigned gpio) { + _set_gpio_det(gpio); } + + template + void for_each_gpio_status(F f) + { + Gppeds_raw::access_t const gppeds = read(); + for(unsigned i = 0; i < Gppeds_raw::ACCESS_WIDTH; i++) { + f(i, gppeds & (1 << i)); } + } + + void clear_event(unsigned gpio) { write(1, gpio); } +}; + +#endif /* _DRIVERS__GPIO__SPEC__RPI__GPIO_H_ */ diff --git a/repos/os/src/drivers/gpio/spec/rpi2/main.cc b/repos/os/src/drivers/gpio/spec/rpi2/main.cc new file mode 100644 index 000000000..324107e92 --- /dev/null +++ b/repos/os/src/drivers/gpio/spec/rpi2/main.cc @@ -0,0 +1,107 @@ +/* + * \brief Gpio driver for the RaspberryPI + * \author Reinier Millo Sánchez + * \author Alexy Gallardo Segura + * \author Humberto Lopéz Leon + * \date 2015-07-23 + */ + +/* + * Copyright (C) 2015-2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +/* Genode includes */ +#include +#include +#include +#include +#include +#include +#include + +/* local includes */ +#include "driver.h" + + +Gpio::Rpi_driver& Gpio::Rpi_driver::factory(Genode::Env &env) +{ + static Rpi_driver driver(env); + return driver; +} + + +struct Main +{ + Genode::Env &env; + Genode::Sliced_heap sliced_heap; + Gpio::Rpi_driver &driver; + Gpio::Root root; + + Genode::Attached_rom_dataspace config_rom { env, "config" }; + + Main(Genode::Env &env) + : + env(env), + sliced_heap(env.ram(), env.rm()), + driver(Gpio::Rpi_driver::factory(env)), + root(&env.ep().rpc_ep(), &sliced_heap, driver) + { + using namespace Genode; + log("--- Raspberry Pi GPIO driver ---"); + + /* + * Check configuration for async events detect + */ + unsigned int async = 0; + try { + config_rom.xml().attribute("async_events").value(&async); + } catch (...) { } + driver.set_async_events(async>0); + + /* + * Check for common GPIO configuration + */ + Gpio::process_config(config_rom.xml(), driver); + + /* + * Check configuration for specific function + */ + try { + Xml_node gpio_node = config_rom.xml().sub_node("gpio"); + + for (;; gpio_node = gpio_node.next("gpio")) { + unsigned num = 0; + unsigned function = 0; + + try { + gpio_node.attribute("num").value(&num); + gpio_node.attribute("function").value(&function); + + switch(function){ + case 0: driver.set_func(num, Gpio::Reg::FSEL_ALT0); break; + case 1: driver.set_func(num, Gpio::Reg::FSEL_ALT1); break; + case 2: driver.set_func(num, Gpio::Reg::FSEL_ALT2); break; + case 3: driver.set_func(num, Gpio::Reg::FSEL_ALT3); break; + case 4: driver.set_func(num, Gpio::Reg::FSEL_ALT4); break; + case 5: driver.set_func(num, Gpio::Reg::FSEL_ALT5); break; + default: warning("wrong pin function, ignore node"); + } + } catch(Xml_node::Nonexistent_attribute) { + warning("missing attribute, ignore node"); + } + if (gpio_node.last("gpio")) break; + } + } catch (Xml_node::Nonexistent_sub_node) { warning("no GPIO config"); } + + /* + * Announce service + */ + env.parent().announce(env.ep().manage(root)); + } +}; + + +void Component::construct(Genode::Env &env) { static Main main(env); } diff --git a/repos/os/src/drivers/platform/spec/rpi2/framebuffer_message.h b/repos/os/src/drivers/platform/spec/rpi2/framebuffer_message.h new file mode 100644 index 000000000..8a325642c --- /dev/null +++ b/repos/os/src/drivers/platform/spec/rpi2/framebuffer_message.h @@ -0,0 +1,63 @@ +/* + * \brief Marshalling of mbox messages for framebuffer channel + * \author Norman Feske + * \date 2013-09-15 + */ + +/* + * Copyright (C) 2013-2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _FRAMEBUFFER_MESSAGE_H_ +#define _FRAMEBUFFER_MESSAGE_H_ + +/* Genode includes */ +#include +#include + +/* board-specific includes */ +#include +#include + +namespace Platform { struct Framebuffer_message; } + + +/** + * Mailbox message buffer for the framebuffer channel + */ +struct Platform::Framebuffer_message : Framebuffer_info +{ + Framebuffer_message(Framebuffer_info const &info) : Framebuffer_info(info) { } + + void finalize() { } + + static unsigned channel() { return 1; } + + static Rpi::Videocore_cache_policy cache_policy() { + return Rpi::COHERENT; + } + + void dump(char const *label) + { + using Genode::printf; + + printf("%s message:\n", label); + printf(" phys_width: %u\n", phys_width); + printf(" phys_height: %u\n", phys_height); + printf(" virt_width: %u\n", virt_width); + printf(" virt_height: %u\n", virt_height); + printf(" pitch: %u\n", pitch); + printf(" depth: %d\n", depth); + printf(" x_offset: %d\n", x_offset); + printf(" y_offset: %d\n", y_offset); + printf(" addr: 0x%08x\n", addr); + printf(" size: 0x%08x\n", size); + } + + inline void *operator new (__SIZE_TYPE__, void *ptr) { return ptr; } +}; + +#endif /* _FRAMEBUFFER_MESSAGE_H_ */ diff --git a/repos/os/src/drivers/platform/spec/rpi2/main.cc b/repos/os/src/drivers/platform/spec/rpi2/main.cc new file mode 100644 index 000000000..eff4a382f --- /dev/null +++ b/repos/os/src/drivers/platform/spec/rpi2/main.cc @@ -0,0 +1,118 @@ +/* + * \brief Driver for Raspberry Pi specific platform devices + * \author Norman Feske + * \date 2013-09-16 + */ + +/* + * Copyright (C) 2013-2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +/* Genode includes */ +#include +#include +#include +#include + +/* platform includes */ +#include +#include + +/* local includes */ +#include +#include +#include + + +namespace Platform { + class Session_component; + class Root; +} + + +class Platform::Session_component : public Genode::Rpc_object +{ + private: + + Mbox &_mbox; + + public: + + Session_component(Mbox &mbox) : _mbox(mbox) { } + + + /********************************** + ** Platform session interface ** + **********************************/ + + void setup_framebuffer(Framebuffer_info &info) + { + auto const &msg = _mbox.message(info); + _mbox.call(); + info = msg; + } + + bool power_state(Power id) + { + auto &msg = _mbox.message(); + auto const &res = msg.append(id); + _mbox.call(); + return res.state; + } + + void power_state(Power id, bool enable) + { + auto &msg = _mbox.message(); + msg.append_no_response(id, enable, true); + _mbox.call(); + } + + uint32_t clock_rate(Clock id) + { + auto &msg = _mbox.message(); + auto const &res = msg.append(id); + _mbox.call(); + return res.hz; + } +}; + + +class Platform::Root : public Genode::Root_component +{ + private: + + Mbox _mbox; + + protected: + + Session_component *_create_session(const char *) { + return new (md_alloc()) Session_component(_mbox); } + + public: + + Root(Env& env, Allocator & md_alloc) + : Root_component(env.ep(), md_alloc), _mbox(env) + { } +}; + + +struct Main +{ + Genode::Env & env; + Genode::Heap heap { env.ram(), env.rm() }; + Platform::Root root { env, heap }; + + Main(Genode::Env & env) : env(env) { + env.parent().announce(env.ep().manage(root)); } +}; + + +void Component::construct(Genode::Env &env) +{ + Genode::log("--- Raspberry Pi platform driver ---"); + + static Main main(env); +} diff --git a/repos/os/src/drivers/platform/spec/rpi2/mbox.h b/repos/os/src/drivers/platform/spec/rpi2/mbox.h new file mode 100644 index 000000000..6dff9d94d --- /dev/null +++ b/repos/os/src/drivers/platform/spec/rpi2/mbox.h @@ -0,0 +1,127 @@ +/* + * \brief Mbox for communicating between Videocore and ARM + * \author Norman Feske + * \date 2013-09-14 + */ + +/* + * Copyright (C) 2013-2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _DRIVERS__PLATFORM__SPEC__RPI__MBOX_H_ +#define _DRIVERS__PLATFORM__SPEC__RPI__MBOX_H_ + +/* Genode includes */ +#include +#include +#include +#include +#include +#include +#include + +class Mbox : Genode::Attached_mmio +{ + private: + + Genode::Env &_env; + + enum { verbose = false }; + + typedef Genode::addr_t addr_t; + typedef Genode::uint32_t uint32_t; + typedef Genode::Dataspace_client Dataspace_client; + + enum { BASE = 0x3f00b800, + SIZE = 0x100 }; + + struct Read : Register<0x80, 32> { }; + + struct Status : Register<0x98, 32> + { + struct Rd_empty : Bitfield<30, 1> { }; + struct Wr_full : Bitfield<31, 1> { }; + }; + + struct Write : Register<0xa0, 32> + { + struct Channel : Bitfield<0, 4> { }; + struct Value : Bitfield<4, 26> { }; + struct Cache_policy : Bitfield<30, 2> { }; + }; + + enum { MSG_BUFFER_SIZE = 0x1000 }; + Genode::Attached_ram_dataspace _msg_buffer { _env.ram(), _env.rm(), + MSG_BUFFER_SIZE }; + + addr_t const _msg_phys = { Dataspace_client(_msg_buffer.cap()).phys_addr() }; + + struct Delayer : Mmio::Delayer + { + Timer::Connection timer; + void usleep(unsigned us) { timer.usleep(us); } + + Delayer(Genode::Env &env) : timer(env) { } + } _delayer { _env }; + + template + MESSAGE &_message() + { + return *_msg_buffer.local_addr(); + } + + public: + + Mbox(Genode::Env &env) + : Genode::Attached_mmio(env, BASE, SIZE), _env(env) { } + + /** + * Return reference to typed message buffer + */ + template + MESSAGE &message(ARGS... args) + { + return *(new (_msg_buffer.local_addr()) MESSAGE(args...)); + } + + template + void call() + { + _message().finalize(); + + if (verbose) + _message().dump("Input"); + + /* flush pending data in the read buffer */ + while (!read()) + read(); + + try { wait_for(Attempts(500), Microseconds(1), _delayer, + Status::Wr_full::Equal(0)); } + catch (Polling_timeout) { + Genode::error("Mbox: timeout waiting for ready-to-write"); + return; + } + + Write::access_t value = 0; + Write::Channel:: set(value, MESSAGE::channel()); + Write::Value:: set(value, _msg_phys >> Write::Value::SHIFT); + Write::Cache_policy::set(value, MESSAGE::cache_policy()); + write(value); + + try { wait_for(Attempts(500), Microseconds(1), _delayer, + Status::Rd_empty::Equal(0)); } + catch (Polling_timeout) { + Genode::error("Mbox: timeout waiting for response"); + return; + } + + if (verbose) + _message().dump("Output"); + } +}; + +#endif /* _DRIVERS__PLATFORM__SPEC__RPI__MBOX_H_ */ diff --git a/repos/os/src/drivers/platform/spec/rpi2/property_command.h b/repos/os/src/drivers/platform/spec/rpi2/property_command.h new file mode 100644 index 000000000..13bc48101 --- /dev/null +++ b/repos/os/src/drivers/platform/spec/rpi2/property_command.h @@ -0,0 +1,133 @@ +/* + * \brief Command definitions for the property mbox channel + * \author Norman Feske + * \date 2013-09-15 + */ + +/* + * Copyright (C) 2013-2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _PROPERTY_COMMAND_H_ +#define _PROPERTY_COMMAND_H_ + +/* Genode includes */ +#include + +namespace Property_command { + + using namespace Genode; + + struct Get_power_state + { + static uint32_t opcode() { return 0x00020001; }; + + struct Request + { + uint32_t const device_id; + + Request(uint32_t device_id) : device_id(device_id) { } + }; + + struct Response + { + uint32_t const device_id = 0; + uint32_t const state = 0; + }; + }; + + struct Set_power_state + { + static uint32_t opcode() { return 0x00028001; }; + + struct Request + { + uint32_t const device_id; + uint32_t const state; + + Request(uint32_t device_id, bool enable, bool wait) + : + device_id(device_id), + state(enable | (wait << 1)) + { } + }; + + struct Response + { + uint32_t const device_id = 0; + uint32_t const state = 0; + }; + }; + + struct Get_clock_rate + { + static uint32_t opcode() { return 0x00030002; }; + + struct Request + { + uint32_t const clock_id; + + Request(uint32_t clock_id) : clock_id(clock_id) { } + }; + + struct Response + { + uint32_t const clock_id = 0; + uint32_t const hz = 0; + }; + }; + + struct Allocate_buffer + { + static uint32_t opcode() { return 0x00040001; }; + + struct Request + { + uint32_t const alignment = 0x100; + }; + + struct Response + { + uint32_t const address = 0; + uint32_t const size = 0; + }; + }; + + + struct Release_buffer + { + static uint32_t opcode() { return 0x00048001; }; + }; + + + struct Get_physical_w_h + { + static uint32_t opcode() { return 0x00040003; }; + + struct Response + { + uint32_t const width = 0; + uint32_t const height = 0; + }; + }; + + + struct Set_physical_w_h + { + static uint32_t opcode() { return 0x00048003; }; + + struct Request + { + uint32_t const width; + uint32_t const height; + + Request(uint32_t width, uint32_t height) + : width(width), height(height) { } + }; + }; +} + +#endif /* _PROPERTY_COMMAND_H_ */ diff --git a/repos/os/src/drivers/platform/spec/rpi2/target.mk b/repos/os/src/drivers/platform/spec/rpi2/target.mk new file mode 100644 index 000000000..3d818daaa --- /dev/null +++ b/repos/os/src/drivers/platform/spec/rpi2/target.mk @@ -0,0 +1,8 @@ +TARGET = platform_drv +REQUIRES = rpi2 +SRC_CC = main.cc +INC_DIR += ${PRG_DIR} +LIBS = base + +# enable C++11 support +CC_CXX_OPT += -std=gnu++11 diff --git a/tool/create_builddir b/tool/create_builddir index 2c98ae525..62c8f8b1c 100755 --- a/tool/create_builddir +++ b/tool/create_builddir @@ -10,7 +10,7 @@ MAKEOVERRIDES = PLATFORM = $(MAKECMDGOALS) -PLATFORMS = x86_32 x86_64 panda pbxa9 rpi arndale imx53_qsb imx53_qsb_tz \ +PLATFORMS = x86_32 x86_64 panda pbxa9 rpi rpi2 arndale imx53_qsb imx53_qsb_tz \ usb_armory wand_quad sabre_lite odroid_xu odroid_x2 zynq_qemu muen \ riscv_spike linux bb_x15 @@ -139,6 +139,7 @@ BUILD_CONF(x86_64) := run_kernel_x86_64 $(BUILD_CONF_X86_64) BUILD_CONF(pbxa9) := run_kernel_hw_foc $(BUILD_CONF_PBXA9) BUILD_CONF(panda) := run_kernel_hw_foc run_boot_dir repos BUILD_CONF(rpi) := run_kernel_hw_foc run_boot_dir repos +BUILD_CONF(rpi2) := run_kernel_foc run_boot_dir repos BUILD_CONF(arndale) := run_kernel_hw_foc run_boot_dir repos BUILD_CONF(imx53_qsb) := run_kernel_hw run_boot_dir repos BUILD_CONF(imx53_qsb_tz) := run_kernel_hw run_boot_dir repos @@ -224,6 +225,7 @@ SPECS(x86_64) := x86_64 SPECS(pbxa9) := pbxa9 SPECS(panda) := panda SPECS(rpi) := rpi +SPECS(rpi2) := rpi2 SPECS(arndale) := arndale SPECS(imx53_qsb) := imx53_qsb SPECS(imx53_qsb_tz) := imx53_qsb trustzone diff --git a/tool/run/boot_dir/foc b/tool/run/boot_dir/foc index d22c877db..7ddd744b5 100644 --- a/tool/run/boot_dir/foc +++ b/tool/run/boot_dir/foc @@ -12,6 +12,7 @@ proc core_link_address { } { if {[have_spec x86 ]} { return "0x01100000" } if {[have_spec arndale ]} { return "0x80100000" } if {[have_spec rpi ]} { return "0x00800000" } + if {[have_spec rpi2 ]} { return "0x00800000" } if {[have_spec panda ]} { return "0xa0000000" } if {[have_spec pbxa9 ]} { return "0x76000000" } if {[have_spec odroid_x2]} { return "0x80100000" }