mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-20 09:46:20 +00:00
parent
00f7819623
commit
c99ca21649
@ -1,67 +0,0 @@
|
||||
/*
|
||||
* \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 <util/mmio.h>
|
||||
|
||||
namespace Rpi {
|
||||
enum {
|
||||
RAM_0_BASE = 0x00000000,
|
||||
RAM_0_SIZE = 0x10000000, /* XXX ? */
|
||||
|
||||
MMIO_0_BASE = 0x20000000,
|
||||
MMIO_0_SIZE = 0x02000000,
|
||||
|
||||
SYSTEM_TIMER_IRQ = 1,
|
||||
SYSTEM_TIMER_MMIO_BASE = 0x20003000,
|
||||
SYSTEM_TIMER_MMIO_SIZE = 0x1000,
|
||||
SYSTEM_TIMER_CLOCK = 1000000,
|
||||
|
||||
PL011_0_IRQ = 57,
|
||||
PL011_0_MMIO_BASE = 0x20201000,
|
||||
PL011_0_MMIO_SIZE = 0x1000,
|
||||
PL011_0_CLOCK = 3000000,
|
||||
|
||||
PL011_1_IRQ = 61,
|
||||
PL011_1_MMIO_BASE = 0x20215000,
|
||||
PL011_1_MMIO_SIZE = 0x1000,
|
||||
PL011_1_CLOCK = 3000000,
|
||||
|
||||
IRQ_CONTROLLER_BASE = 0x2000b200,
|
||||
IRQ_CONTROLLER_SIZE = 0x100,
|
||||
|
||||
GPIO_CONTROLLER_BASE = 0x20200000,
|
||||
GPIO_CONTROLLER_SIZE = 0x1000,
|
||||
|
||||
USB_DWC_OTG_BASE = 0x20980000,
|
||||
USB_DWC_OTG_SIZE = 0x20000,
|
||||
|
||||
/* USB host controller */
|
||||
DWC_IRQ = 9,
|
||||
|
||||
/* 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_ */
|
@ -1,7 +1,6 @@
|
||||
proc have_platform_drv {} {
|
||||
return [expr [have_board imx53_qsb] \
|
||||
|| [have_board imx53_qsb_tz] \
|
||||
|| [have_board rpi] \
|
||||
|| [have_board pc]]
|
||||
}
|
||||
|
||||
@ -66,7 +65,6 @@ proc append_platform_drv_build_components {} {
|
||||
proc platform_drv_binary {} {
|
||||
if {[have_board imx53_qsb]} { return legacy_imx53_platform_drv }
|
||||
if {[have_board imx53_qsb_tz]} { return legacy_imx53_platform_drv }
|
||||
if {[have_board rpi]} { return rpi_platform_drv }
|
||||
if {[have_board pc]} { return legacy_pc_platform_drv }
|
||||
return no_platform_drv_available
|
||||
}
|
||||
|
@ -1,3 +0,0 @@
|
||||
|
||||
Device drivers needed to run interactive
|
||||
scenarios on Raspberry Pi 1
|
@ -1,7 +0,0 @@
|
||||
_/raw/drivers_interactive-rpi
|
||||
_/src/event_filter
|
||||
_/src/report_rom
|
||||
_/src/rpi_fb_drv
|
||||
_/src/platform_drv
|
||||
_/src/usb_hid_drv
|
||||
_/src/usb_host_drv
|
@ -1 +0,0 @@
|
||||
2022-01-18 ae83537a60f37a586d1744066b8e04439e469191
|
@ -1,7 +0,0 @@
|
||||
content: drivers.config fb_drv.config event_filter.config en_us.chargen special.chargen
|
||||
|
||||
drivers.config fb_drv.config event_filter.config:
|
||||
cp $(REP_DIR)/recipes/raw/drivers_interactive-rpi/$@ $@
|
||||
|
||||
en_us.chargen special.chargen:
|
||||
cp $(GENODE_DIR)/repos/os/src/server/event_filter/$@ $@
|
@ -1,135 +0,0 @@
|
||||
<config>
|
||||
|
||||
<parent-provides>
|
||||
<service name="IRQ"/>
|
||||
<service name="IO_MEM"/>
|
||||
<service name="ROM"/>
|
||||
<service name="PD"/>
|
||||
<service name="RM"/>
|
||||
<service name="CPU"/>
|
||||
<service name="LOG"/>
|
||||
<service name="Timer"/>
|
||||
<service name="Capture"/>
|
||||
<service name="Event"/>
|
||||
</parent-provides>
|
||||
|
||||
<default caps="60"/>
|
||||
|
||||
<start name="report_rom">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
<provides> <service name="Report"/> <service name="ROM"/> </provides>
|
||||
<config verbose="no">
|
||||
<default-policy report="usb_drv -> devices"/>
|
||||
</config>
|
||||
<route>
|
||||
<any-service> <parent/> </any-service>
|
||||
</route>
|
||||
</start>
|
||||
|
||||
<start name="rpi_platform_drv" caps="200">
|
||||
<resource name="RAM" quantum="2M"/>
|
||||
<provides> <service name="Platform"/> </provides>
|
||||
<config>
|
||||
|
||||
<device name="dwc_otg" type="brcm,bcm2835-usb">
|
||||
<io_mem address="0x20980000" size="0x10000"/>
|
||||
<irq number="9"/>
|
||||
<power-domain name="usb"/>
|
||||
</device>
|
||||
<policy label_prefix="usb_drv" info="yes">
|
||||
<device name="dwc_otg"/>
|
||||
</policy>
|
||||
|
||||
</config>
|
||||
<route>
|
||||
<service name="IRQ"> <parent/> </service>
|
||||
<service name="IO_MEM"> <parent/> </service>
|
||||
<service name="ROM"> <parent/> </service>
|
||||
<service name="PD"> <parent/> </service>
|
||||
<service name="RM"> <parent/> </service>
|
||||
<service name="CPU"> <parent/> </service>
|
||||
<service name="LOG"> <parent/> </service>
|
||||
<service name="Timer"> <parent/> </service>
|
||||
</route>
|
||||
</start>
|
||||
|
||||
<start name="legacy_rpi_platform_drv" caps="200">
|
||||
<resource name="RAM" quantum="3M"/>
|
||||
<provides>
|
||||
<service name="Platform"/>
|
||||
</provides>
|
||||
<route>
|
||||
<service name="IRQ"> <parent/> </service>
|
||||
<service name="IO_MEM"> <parent/> </service>
|
||||
<service name="ROM"> <parent/> </service>
|
||||
<service name="PD"> <parent/> </service>
|
||||
<service name="CPU"> <parent/> </service>
|
||||
<service name="LOG"> <parent/> </service>
|
||||
<service name="Timer"> <parent/> </service>
|
||||
</route>
|
||||
</start>
|
||||
|
||||
<start name="event_filter" caps="80">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
<provides> <service name="Event"/> </provides>
|
||||
<route>
|
||||
<service name="ROM" label="config"> <parent label="event_filter.config"/> </service>
|
||||
<service name="Event"> <parent/> </service>
|
||||
<any-service> <parent/> </any-service>
|
||||
</route>
|
||||
</start>
|
||||
|
||||
<start name="usb_drv" caps="150">
|
||||
<binary name="rpi_usb_host_drv"/>
|
||||
<resource name="RAM" quantum="12M"/>
|
||||
<provides> <service name="Usb"/> </provides>
|
||||
<config bios_handoff="yes">
|
||||
<report devices="yes"/>
|
||||
<policy label_prefix="usb_hid_drv" class="0x3"/>
|
||||
</config>
|
||||
<route>
|
||||
<service name="Report"> <child name="report_rom"/> </service>
|
||||
<service name="RM"> <parent/> </service>
|
||||
<service name="ROM"> <parent/> </service>
|
||||
<service name="PD"> <parent/> </service>
|
||||
<service name="CPU"> <parent/> </service>
|
||||
<service name="LOG"> <parent/> </service>
|
||||
<service name="Timer"> <parent/> </service>
|
||||
<service name="Platform"> <child name="rpi_platform_drv"/> </service>
|
||||
</route>
|
||||
</start>
|
||||
|
||||
<start name="usb_hid_drv" caps="140">
|
||||
<resource name="RAM" quantum="11M"/>
|
||||
<provides><service name="Input"/></provides>
|
||||
<config use_report="yes"/>
|
||||
<route>
|
||||
<service name="ROM" label="report"> <child name="report_rom"/> </service>
|
||||
<service name="Event"> <child name="event_filter" label="usb"/> </service>
|
||||
<service name="RM"> <parent/> </service>
|
||||
<service name="ROM"> <parent/> </service>
|
||||
<service name="PD"> <parent/> </service>
|
||||
<service name="CPU"> <parent/> </service>
|
||||
<service name="LOG"> <parent/> </service>
|
||||
<service name="Timer"> <parent/> </service>
|
||||
<service name="Usb"> <child name="usb_drv"/> </service>
|
||||
</route>
|
||||
</start>
|
||||
|
||||
<start name="fb_drv" caps="120">
|
||||
<binary name="rpi_fb_drv"/>
|
||||
<resource name="RAM" quantum="4M"/>
|
||||
<route>
|
||||
<service name="ROM" label="config"> <parent label="fb_drv.config"/> </service>
|
||||
<service name="Platform"> <child name="legacy_rpi_platform_drv"/> </service>
|
||||
<service name="IO_MEM"> <parent/> </service>
|
||||
<service name="ROM"> <parent/> </service>
|
||||
<service name="PD"> <parent/> </service>
|
||||
<service name="CPU"> <parent/> </service>
|
||||
<service name="LOG"> <parent/> </service>
|
||||
<service name="Timer"> <parent/> </service>
|
||||
<service name="Capture"> <parent/> </service>
|
||||
</route>
|
||||
</start>
|
||||
|
||||
</config>
|
@ -1,22 +0,0 @@
|
||||
<config>
|
||||
<output>
|
||||
<chargen>
|
||||
<merge>
|
||||
<input name="usb"/>
|
||||
</merge>
|
||||
<mod1>
|
||||
<key name="KEY_LEFTSHIFT"/> <key name="KEY_RIGHTSHIFT"/>
|
||||
</mod1>
|
||||
<mod2>
|
||||
<key name="KEY_LEFTCTRL"/> <key name="KEY_RIGHTCTRL"/>
|
||||
</mod2>
|
||||
<mod3>
|
||||
<key name="KEY_RIGHTALT"/> <!-- AltGr -->
|
||||
</mod3>
|
||||
<repeat delay_ms="230" rate_ms="90"/>
|
||||
<include rom="en_us.chargen"/>
|
||||
<include rom="special.chargen"/>
|
||||
</chargen>
|
||||
</output>
|
||||
<policy label="usb" input="usb"/>
|
||||
</config>
|
@ -1 +0,0 @@
|
||||
<config width="1024" height="768" buffered="yes"/>
|
@ -1 +0,0 @@
|
||||
2022-01-18 fc7a148586797692c9b5118b4f9feb15977d1fff
|
@ -1,3 +0,0 @@
|
||||
|
||||
Device drivers needed for scenarios
|
||||
using one network interface
|
@ -1,4 +0,0 @@
|
||||
_/src/platform_drv
|
||||
_/src/usb_host_drv
|
||||
_/src/usb_net_drv
|
||||
_/raw/drivers_nic-rpi
|
@ -1 +0,0 @@
|
||||
2022-01-18 7d8af3ec212054217e19c0ae9f8e05b620a674a3
|
@ -1,4 +0,0 @@
|
||||
content: drivers.config
|
||||
|
||||
drivers.config:
|
||||
cp $(REP_DIR)/recipes/raw/drivers_nic-rpi/$@ $@
|
@ -1,75 +0,0 @@
|
||||
<config>
|
||||
|
||||
<parent-provides>
|
||||
<service name="IRQ"/>
|
||||
<service name="IO_MEM"/>
|
||||
<service name="IO_PORT"/>
|
||||
<service name="ROM"/>
|
||||
<service name="PD"/>
|
||||
<service name="RM"/>
|
||||
<service name="CPU"/>
|
||||
<service name="LOG"/>
|
||||
<service name="Timer"/>
|
||||
<service name="Uplink"/>
|
||||
</parent-provides>
|
||||
|
||||
<start name="rpi_platform_drv" caps="200">
|
||||
<resource name="RAM" quantum="2M"/>
|
||||
<provides> <service name="Platform"/> </provides>
|
||||
<config>
|
||||
|
||||
<device name="dwc_otg" type="brcm,bcm2835-usb">
|
||||
<io_mem address="0x20980000" size="0x10000"/>
|
||||
<irq number="9"/>
|
||||
<power-domain name="usb"/>
|
||||
</device>
|
||||
<policy label_prefix="rpi_usb_host_drv" info="yes">
|
||||
<device name="dwc_otg"/>
|
||||
</policy>
|
||||
|
||||
</config>
|
||||
<route>
|
||||
<service name="IRQ"> <parent/> </service>
|
||||
<service name="IO_MEM"> <parent/> </service>
|
||||
<service name="ROM"> <parent/> </service>
|
||||
<service name="PD"> <parent/> </service>
|
||||
<service name="RM"> <parent/> </service>
|
||||
<service name="CPU"> <parent/> </service>
|
||||
<service name="LOG"> <parent/> </service>
|
||||
<service name="Timer"> <parent/> </service>
|
||||
</route>
|
||||
</start>
|
||||
|
||||
<start name="rpi_usb_host_drv" caps="120">
|
||||
<resource name="RAM" quantum="10M"/>
|
||||
<provides> <service name="Usb"/> </provides>
|
||||
<config bios_handoff="yes">
|
||||
<policy label_prefix="usb_net_drv" vendor_id="0x0424" product_id="0xec00"/> }
|
||||
</config>
|
||||
<route>
|
||||
<service name="ROM"> <parent/> </service>
|
||||
<service name="PD"> <parent/> </service>
|
||||
<service name="RM"> <parent/> </service>
|
||||
<service name="CPU"> <parent/> </service>
|
||||
<service name="LOG"> <parent/> </service>
|
||||
<service name="Timer"> <parent/> </service>
|
||||
<service name="Platform"> <child name="rpi_platform_drv"/> </service>
|
||||
</route>
|
||||
</start>
|
||||
|
||||
<start name="usb_net_drv" caps="120">
|
||||
<resource name="RAM" quantum="15M"/>
|
||||
<config mode="uplink_client" mac="02:00:00:00:01:01" />
|
||||
<route>
|
||||
<service name="ROM"> <parent/> </service>
|
||||
<service name="PD"> <parent/> </service>
|
||||
<service name="RM"> <parent/> </service>
|
||||
<service name="CPU"> <parent/> </service>
|
||||
<service name="LOG"> <parent/> </service>
|
||||
<service name="Timer"> <parent/> </service>
|
||||
<service name="Uplink"> <parent/> </service>
|
||||
<service name="Usb"> <child name="rpi_usb_host_drv"/> </service>
|
||||
</route>
|
||||
</start>
|
||||
|
||||
</config>
|
@ -1 +0,0 @@
|
||||
2022-01-18 48c889fe114b5c7932fa584ac40b084a3ce6deff
|
@ -1,59 +0,0 @@
|
||||
/*
|
||||
* \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 _INCLUDE__LEGACY__RPI__PLATFORM__FRAMEBUFFER_INFO_H_
|
||||
#define _INCLUDE__LEGACY__RPI__PLATFORM__FRAMEBUFFER_INFO_H_
|
||||
|
||||
#include <base/stdint.h>
|
||||
|
||||
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 /* _INCLUDE__LEGACY__RPI__PLATFORM__FRAMEBUFFER_INFO_H_ */
|
@ -1,209 +0,0 @@
|
||||
/*
|
||||
* \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 _INCLUDE__LEGACY__RPI__PLATFORM__PROPERTY_MESSAGE_H_
|
||||
#define _INCLUDE__LEGACY__RPI__PLATFORM__PROPERTY_MESSAGE_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/misc_math.h>
|
||||
#include <util/construct_at.h>
|
||||
#include <base/log.h>
|
||||
|
||||
/* board-specific includes */
|
||||
#include <drivers/defs/rpi.h>
|
||||
|
||||
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 <typename TAG>
|
||||
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 <typename T>
|
||||
static size_t response_size(typename T::Response *)
|
||||
{
|
||||
return sizeof(typename T::Response);
|
||||
}
|
||||
|
||||
template <typename>
|
||||
static size_t response_size(...)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static size_t request_size(typename T::Request *)
|
||||
{
|
||||
return sizeof(typename T::Request);
|
||||
}
|
||||
|
||||
template <typename>
|
||||
static size_t request_size(...)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename T, typename... ARGS>
|
||||
void construct_request(typename T::Request *, ARGS... args)
|
||||
{
|
||||
construct_at<typename T::Request>(payload, args...);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void construct_response(typename T::Response *)
|
||||
{
|
||||
construct_at<typename T::Response>(payload);
|
||||
}
|
||||
|
||||
template <typename>
|
||||
void construct_response(...) { }
|
||||
|
||||
static constexpr size_t payload_size()
|
||||
{
|
||||
return max(request_size<TAG>(0), response_size<TAG>(0));
|
||||
}
|
||||
|
||||
template <typename... REQUEST_ARGS>
|
||||
Tag(REQUEST_ARGS... request_args)
|
||||
:
|
||||
opcode(TAG::opcode()),
|
||||
buf_size(payload_size()),
|
||||
len(request_size<TAG>(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<TAG>(0);
|
||||
construct_request<TAG>(0, request_args...);
|
||||
}
|
||||
};
|
||||
|
||||
void reset()
|
||||
{
|
||||
buf_size = 0;
|
||||
code = REQUEST;
|
||||
}
|
||||
|
||||
/**
|
||||
* \return reference to tag in the message buffer
|
||||
*/
|
||||
template <typename POLICY, typename... REQUEST_ARGS>
|
||||
typename POLICY::Response const &append(REQUEST_ARGS... request_args)
|
||||
{
|
||||
auto *tag = construct_at<Tag<POLICY> >(buffer + buf_size, request_args...);
|
||||
|
||||
buf_size += sizeof(Tag<POLICY>) + Tag<POLICY>::payload_size();
|
||||
|
||||
return *(typename POLICY::Response *)tag->payload;
|
||||
}
|
||||
|
||||
template <typename POLICY, typename... REQUEST_ARGS>
|
||||
void append_no_response(REQUEST_ARGS... request_args)
|
||||
{
|
||||
construct_at<Tag<POLICY> >(buffer + buf_size, request_args...);
|
||||
|
||||
buf_size += sizeof(Tag<POLICY>) + Tag<POLICY>::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;
|
||||
log(label, " message:");
|
||||
for (unsigned i = 0;; i++) {
|
||||
for (unsigned j = 0; j < 8; j++) {
|
||||
unsigned const msg_word_idx = i*8 + j;
|
||||
log(" ", Hex(buf[msg_word_idx]));
|
||||
if (msg_word_idx*sizeof(unsigned) < buf_size)
|
||||
continue;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__LEGACY__RPI__PLATFORM__PROPERTY_MESSAGE_H_ */
|
@ -1,41 +0,0 @@
|
||||
/*
|
||||
* \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__LEGACY__RPI__PLATFORM_SESSION__CLIENT_H_
|
||||
#define _INCLUDE__LEGACY__RPI__PLATFORM_SESSION__CLIENT_H_
|
||||
|
||||
#include <base/capability.h>
|
||||
#include <base/rpc_client.h>
|
||||
#include <legacy/rpi/platform_session/platform_session.h>
|
||||
|
||||
namespace Platform { struct Client; }
|
||||
|
||||
struct Platform::Client : Genode::Rpc_client<Platform::Session>
|
||||
{
|
||||
explicit Client(Capability<Session> session)
|
||||
: Genode::Rpc_client<Session>(session) { }
|
||||
|
||||
void setup_framebuffer(Framebuffer_info &info) override {
|
||||
call<Rpc_setup_framebuffer>(info); }
|
||||
|
||||
bool power_state(Power power) override {
|
||||
return call<Rpc_get_power_state>(power); }
|
||||
|
||||
void power_state(Power power, bool enable) override {
|
||||
call<Rpc_set_power_state>(power, enable); }
|
||||
|
||||
uint32_t clock_rate(Clock clock) override {
|
||||
return call<Rpc_get_clock_rate>(clock); }
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__LEGACY__RPI__PLATFORM_SESSION__CLIENT_H_ */
|
@ -1,35 +0,0 @@
|
||||
/*
|
||||
* \brief Connection to platform service
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2013-04-29
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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__LEGACY__RPI__PLATFORM_SESSION__CONNECTION_H_
|
||||
#define _INCLUDE__LEGACY__RPI__PLATFORM_SESSION__CONNECTION_H_
|
||||
|
||||
#include <legacy/rpi/platform_session/client.h>
|
||||
#include <util/arg_string.h>
|
||||
#include <base/connection.h>
|
||||
|
||||
namespace Platform { struct Connection; }
|
||||
|
||||
|
||||
struct Platform::Connection : Genode::Connection<Session>, Client
|
||||
{
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Connection(Genode::Env &env)
|
||||
: Genode::Connection<Session>(env, session(env.parent(),
|
||||
"ram_quota=6K, cap_quota=%u", CAP_QUOTA)),
|
||||
Client(cap()) { }
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__LEGACY__RPI__PLATFORM_SESSION__CONNECTION_H_ */
|
@ -1,89 +0,0 @@
|
||||
/*
|
||||
* \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__LEGACY__RPI__PLATFORM_SESSION__PLATFORM_SESSION_H_
|
||||
#define _INCLUDE__LEGACY__RPI__PLATFORM_SESSION__PLATFORM_SESSION_H_
|
||||
|
||||
#include <base/capability.h>
|
||||
#include <base/rpc.h>
|
||||
#include <dataspace/capability.h>
|
||||
#include <legacy/rpi/platform/framebuffer_info.h>
|
||||
|
||||
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__LEGACY__RPI__PLATFORM_SESSION__PLATFORM_SESSION_H_ */
|
@ -1,7 +1,5 @@
|
||||
INCLUDE_SUB_DIRS := platform_session \
|
||||
legacy/imx53/platform_session \
|
||||
legacy/rpi/platform \
|
||||
legacy/rpi/platform_session \
|
||||
legacy/x86/platform_session \
|
||||
legacy/x86/platform_device
|
||||
|
||||
|
@ -1,2 +0,0 @@
|
||||
SRC_DIR = src/drivers/framebuffer/rpi
|
||||
include $(GENODE_DIR)/repos/base/recipes/src/content.inc
|
@ -1 +0,0 @@
|
||||
2022-01-18 f69b1ff68fa854cc95c624efd275c4efc53018f1
|
@ -1,5 +0,0 @@
|
||||
base
|
||||
os
|
||||
blit
|
||||
platform_session
|
||||
capture_session
|
@ -1,2 +0,0 @@
|
||||
If you find the red and blue color channels swapped, you may need to specify
|
||||
the option 'framebuffer_swap=1' in you Raspberry Pi's config.txt.
|
@ -1,100 +0,0 @@
|
||||
/*
|
||||
* \brief Framebuffer driver for Raspberry Pi
|
||||
* \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.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/attached_io_mem_dataspace.h>
|
||||
#include <base/attached_ram_dataspace.h>
|
||||
#include <base/attached_rom_dataspace.h>
|
||||
#include <base/component.h>
|
||||
#include <util/reconstructible.h>
|
||||
#include <capture_session/connection.h>
|
||||
#include <legacy/rpi/platform_session/connection.h>
|
||||
#include <blit/blit.h>
|
||||
#include <timer_session/connection.h>
|
||||
|
||||
namespace Framebuffer { struct Main; };
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
/**
|
||||
* The blit library is not free of potential mis-aligned pointer access,
|
||||
* which is not a problem with normal memory. But the Rpi framebuffer driver
|
||||
* uses ordered I/O memory as backend, where mis-aligned memory access is a problem.
|
||||
* Therefore, we do not use the blit library here, but implement a simple
|
||||
* blit function ourselves.
|
||||
*/
|
||||
extern "C" void blit(void const * s, unsigned src_w,
|
||||
void * d, unsigned dst_w, int w, int h)
|
||||
{
|
||||
char const *src = (char const *)s;
|
||||
char *dst = (char *)d;
|
||||
|
||||
if (w <= 0 || h <= 0) return;
|
||||
|
||||
for (; h--; src += (src_w-w), dst += (dst_w-w))
|
||||
for (int i = (w >> 2); i--; src += 4, dst += 4)
|
||||
*(uint32_t *)dst = *(uint32_t const *)src;
|
||||
}
|
||||
|
||||
|
||||
struct Framebuffer::Main
|
||||
{
|
||||
using Area = Capture::Area;
|
||||
using Pixel = Capture::Pixel;
|
||||
|
||||
Env &_env;
|
||||
|
||||
Attached_rom_dataspace _config { _env, "config" };
|
||||
|
||||
Platform::Connection _platform { _env };
|
||||
|
||||
Area const _size { 1024, 768 };
|
||||
|
||||
Platform::Framebuffer_info _fb_info { _size.w(), _size.h(), 32 };
|
||||
|
||||
bool const _fb_initialized = ( _platform.setup_framebuffer(_fb_info), true );
|
||||
|
||||
Attached_io_mem_dataspace _fb_ds { _env, _fb_info.addr, _fb_info.size };
|
||||
|
||||
Capture::Connection _capture { _env };
|
||||
|
||||
Capture::Connection::Screen _captured_screen { _capture, _env.rm(), _size };
|
||||
|
||||
Timer::Connection _timer { _env };
|
||||
|
||||
Signal_handler<Main> _timer_handler { _env.ep(), *this, &Main::_handle_timer };
|
||||
|
||||
void _handle_timer()
|
||||
{
|
||||
Area const phys_size { _fb_info.phys_width, _fb_info.phys_height };
|
||||
|
||||
Surface<Pixel> surface(_fb_ds.local_addr<Pixel>(), phys_size);
|
||||
|
||||
_captured_screen.apply_to_surface(surface);
|
||||
}
|
||||
|
||||
Main(Genode::Env &env) : _env(env)
|
||||
{
|
||||
log("--- rpi_fb_drv started ---");
|
||||
|
||||
_timer.sigh(_timer_handler);
|
||||
_timer.trigger_periodic(10*1000);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void Component::construct(Genode::Env &env)
|
||||
{
|
||||
static Framebuffer::Main main(env);
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
TARGET = rpi_fb_drv
|
||||
REQUIRES = arm_v6
|
||||
SRC_CC = main.cc
|
||||
LIBS = base
|
||||
INC_DIR += $(PRG_DIR)
|
||||
INC_DIR += $(call select_from_repositories,include/spec/rpi)
|
@ -1,61 +0,0 @@
|
||||
/*
|
||||
* \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 <util/misc_math.h>
|
||||
#include <base/log.h>
|
||||
|
||||
/* board-specific includes */
|
||||
#include <drivers/defs/rpi.h>
|
||||
#include <legacy/rpi/platform/framebuffer_info.h>
|
||||
|
||||
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::log;
|
||||
|
||||
log(label, " message:");
|
||||
log(" phys_width: ", phys_width);
|
||||
log(" phys_height: ", phys_height);
|
||||
log(" virt_width: ", virt_width);
|
||||
log(" virt_height: ", virt_height);
|
||||
log(" pitch: ", pitch);
|
||||
log(" depth: ", depth);
|
||||
log(" x_offset: ", x_offset);
|
||||
log(" y_offset: ", y_offset);
|
||||
log(" addr: ", Genode::Hex(addr));
|
||||
log(" size: ", Genode::Hex(size));
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _FRAMEBUFFER_MESSAGE_H_ */
|
@ -1,118 +0,0 @@
|
||||
/*
|
||||
* \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 <base/log.h>
|
||||
#include <base/component.h>
|
||||
#include <base/heap.h>
|
||||
#include <root/component.h>
|
||||
|
||||
/* platform includes */
|
||||
#include <legacy/rpi/platform_session/platform_session.h>
|
||||
#include <legacy/rpi/platform/property_message.h>
|
||||
|
||||
/* local includes */
|
||||
#include <mbox.h>
|
||||
#include <property_command.h>
|
||||
#include <framebuffer_message.h>
|
||||
|
||||
|
||||
namespace Platform {
|
||||
class Session_component;
|
||||
class Root;
|
||||
}
|
||||
|
||||
|
||||
class Platform::Session_component : public Genode::Rpc_object<Platform::Session>
|
||||
{
|
||||
private:
|
||||
|
||||
Mbox &_mbox;
|
||||
|
||||
public:
|
||||
|
||||
Session_component(Mbox &mbox) : _mbox(mbox) { }
|
||||
|
||||
|
||||
/**********************************
|
||||
** Platform session interface **
|
||||
**********************************/
|
||||
|
||||
void setup_framebuffer(Framebuffer_info &info) override
|
||||
{
|
||||
auto const &msg = _mbox.message<Framebuffer_message>(info);
|
||||
_mbox.call<Framebuffer_message>();
|
||||
info = msg;
|
||||
}
|
||||
|
||||
bool power_state(Power id) override
|
||||
{
|
||||
auto &msg = _mbox.message<Property_message>();
|
||||
auto const &res = msg.append<Property_command::Get_power_state>(id);
|
||||
_mbox.call<Property_message>();
|
||||
return res.state;
|
||||
}
|
||||
|
||||
void power_state(Power id, bool enable) override
|
||||
{
|
||||
auto &msg = _mbox.message<Property_message>();
|
||||
msg.append_no_response<Property_command::Set_power_state>(id, enable, true);
|
||||
_mbox.call<Property_message>();
|
||||
}
|
||||
|
||||
uint32_t clock_rate(Clock id) override
|
||||
{
|
||||
auto &msg = _mbox.message<Property_message>();
|
||||
auto const &res = msg.append<Property_command::Get_clock_rate>(id);
|
||||
_mbox.call<Property_message>();
|
||||
return res.hz;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class Platform::Root : public Genode::Root_component<Platform::Session_component>
|
||||
{
|
||||
private:
|
||||
|
||||
Mbox _mbox;
|
||||
|
||||
protected:
|
||||
|
||||
Session_component *_create_session(const char *) override {
|
||||
return new (md_alloc()) Session_component(_mbox); }
|
||||
|
||||
public:
|
||||
|
||||
Root(Env& env, Allocator & md_alloc)
|
||||
: Root_component<Session_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);
|
||||
}
|
@ -1,128 +0,0 @@
|
||||
/*
|
||||
* \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 <util/mmio.h>
|
||||
#include <util/construct_at.h>
|
||||
#include <base/env.h>
|
||||
#include <os/attached_mmio.h>
|
||||
#include <base/attached_ram_dataspace.h>
|
||||
#include <base/log.h>
|
||||
#include <dataspace/client.h>
|
||||
#include <timer_session/connection.h>
|
||||
|
||||
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 = 0x2000b800,
|
||||
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(Genode::uint64_t us) override { timer.usleep(us); }
|
||||
|
||||
Delayer(Genode::Env &env) : timer(env) { }
|
||||
} _delayer { _env };
|
||||
|
||||
template <typename MESSAGE>
|
||||
MESSAGE &_message()
|
||||
{
|
||||
return *_msg_buffer.local_addr<MESSAGE>();
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Mbox(Genode::Env &env)
|
||||
: Genode::Attached_mmio(env, BASE, SIZE), _env(env) { }
|
||||
|
||||
/**
|
||||
* Return reference to typed message buffer
|
||||
*/
|
||||
template <typename MESSAGE, typename... ARGS>
|
||||
MESSAGE &message(ARGS... args)
|
||||
{
|
||||
return *Genode::construct_at<MESSAGE>(_msg_buffer.local_addr<void>(), args...);
|
||||
}
|
||||
|
||||
template <typename MESSAGE>
|
||||
void call()
|
||||
{
|
||||
_message<MESSAGE>().finalize();
|
||||
|
||||
if (verbose)
|
||||
_message<MESSAGE>().dump("Input");
|
||||
|
||||
/* flush pending data in the read buffer */
|
||||
while (!read<Status::Rd_empty>())
|
||||
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<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<MESSAGE>().dump("Output");
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _DRIVERS__PLATFORM__SPEC__RPI__MBOX_H_ */
|
@ -1,133 +0,0 @@
|
||||
/*
|
||||
* \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 <base/stdint.h>
|
||||
|
||||
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_ */
|
@ -1,8 +0,0 @@
|
||||
TARGET = legacy_rpi_platform_drv
|
||||
REQUIRES = arm_v6
|
||||
SRC_CC = main.cc
|
||||
INC_DIR += ${PRG_DIR} $(call select_from_repositories,include/spec/rpi)
|
||||
LIBS = base
|
||||
|
||||
# enable C++11 support
|
||||
CC_CXX_OPT += -std=gnu++11
|
@ -1,54 +0,0 @@
|
||||
/*
|
||||
* \brief Platform driver for Raspberry Pi 1
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2020-04-12
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2020 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.
|
||||
*/
|
||||
|
||||
#include <base/component.h>
|
||||
#include <power_domains.h>
|
||||
#include <root.h>
|
||||
|
||||
namespace Driver { struct Main; };
|
||||
|
||||
struct Driver::Main
|
||||
{
|
||||
void update_config();
|
||||
|
||||
Env & env;
|
||||
Heap heap { env.ram(), env.rm() };
|
||||
Sliced_heap sliced_heap { env.ram(), env.rm() };
|
||||
Attached_rom_dataspace config { env, "config" };
|
||||
Device_model devices { heap };
|
||||
Mbox mbox { env };
|
||||
Power_domains power_domains { devices.powers(), mbox };
|
||||
Signal_handler<Main> config_handler { env.ep(), *this,
|
||||
&Main::update_config };
|
||||
Driver::Root root { env, sliced_heap,
|
||||
config, devices };
|
||||
|
||||
Main(Genode::Env & e)
|
||||
: env(e)
|
||||
{
|
||||
devices.update(config.xml());
|
||||
config.sigh(config_handler);
|
||||
env.parent().announce(env.ep().manage(root));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void Driver::Main::update_config()
|
||||
{
|
||||
config.update();
|
||||
devices.update(config.xml());
|
||||
root.update_policy();
|
||||
}
|
||||
|
||||
void Component::construct(Genode::Env &env) {
|
||||
static Driver::Main main(env); }
|
@ -1,128 +0,0 @@
|
||||
/*
|
||||
* \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 <util/mmio.h>
|
||||
#include <util/construct_at.h>
|
||||
#include <base/env.h>
|
||||
#include <os/attached_mmio.h>
|
||||
#include <base/attached_ram_dataspace.h>
|
||||
#include <base/log.h>
|
||||
#include <dataspace/client.h>
|
||||
#include <timer_session/connection.h>
|
||||
|
||||
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 = 0x2000b800,
|
||||
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(Genode::uint64_t us) override { timer.usleep(us); }
|
||||
|
||||
Delayer(Genode::Env &env) : timer(env) { }
|
||||
} _delayer { _env };
|
||||
|
||||
template <typename MESSAGE>
|
||||
MESSAGE &_message()
|
||||
{
|
||||
return *_msg_buffer.local_addr<MESSAGE>();
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Mbox(Genode::Env &env)
|
||||
: Genode::Attached_mmio(env, BASE, SIZE), _env(env) { }
|
||||
|
||||
/**
|
||||
* Return reference to typed message buffer
|
||||
*/
|
||||
template <typename MESSAGE, typename... ARGS>
|
||||
MESSAGE &message(ARGS... args)
|
||||
{
|
||||
return *Genode::construct_at<MESSAGE>(_msg_buffer.local_addr<void>(), args...);
|
||||
}
|
||||
|
||||
template <typename MESSAGE>
|
||||
void call()
|
||||
{
|
||||
_message<MESSAGE>().finalize();
|
||||
|
||||
if (verbose)
|
||||
_message<MESSAGE>().dump("Input");
|
||||
|
||||
/* flush pending data in the read buffer */
|
||||
while (!read<Status::Rd_empty>())
|
||||
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<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<MESSAGE>().dump("Output");
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _DRIVERS__PLATFORM__SPEC__RPI__MBOX_H_ */
|
@ -1,67 +0,0 @@
|
||||
/*
|
||||
* \brief Platform driver for Raspberry Pi 1
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2021-12-06
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2021 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.
|
||||
*/
|
||||
|
||||
#include <mbox.h>
|
||||
#include <device.h>
|
||||
#include <property_command.h>
|
||||
#include <property_message.h>
|
||||
|
||||
namespace Driver { struct Power_domains; }
|
||||
|
||||
|
||||
struct Driver::Power_domains
|
||||
{
|
||||
struct Domain : Driver::Power
|
||||
{
|
||||
Mbox & mbox;
|
||||
unsigned const id;
|
||||
|
||||
Domain(Powers & powers,
|
||||
Power::Name name,
|
||||
Mbox & mbox,
|
||||
unsigned id)
|
||||
:
|
||||
Power(powers, name), mbox(mbox), id(id) {}
|
||||
|
||||
void _on() override
|
||||
{
|
||||
auto & msg = mbox.message<Property_message>();
|
||||
msg.append_no_response<Property_command::Set_power_state>(id,
|
||||
true,
|
||||
true);
|
||||
mbox.call<Property_message>();
|
||||
}
|
||||
|
||||
void _off() override
|
||||
{
|
||||
auto & msg = mbox.message<Property_message>();
|
||||
msg.append_no_response<Property_command::Set_power_state>(id,
|
||||
false,
|
||||
true);
|
||||
mbox.call<Property_message>();
|
||||
}
|
||||
};
|
||||
|
||||
Powers & powers;
|
||||
Mbox & mbox;
|
||||
|
||||
Domain sdhci { powers, "sdhci", mbox, 0 };
|
||||
Domain uart_0 { powers, "uart_0", mbox, 1 };
|
||||
Domain uart_1 { powers, "uart_1", mbox, 2 };
|
||||
Domain usb { powers, "usb", mbox, 3 };
|
||||
Domain i2c_0 { powers, "i2c_0", mbox, 4 };
|
||||
Domain i2c_1 { powers, "i2c_1", mbox, 5 };
|
||||
Domain i2c_2 { powers, "i2c_2", mbox, 6 };
|
||||
Domain spi { powers, "spi", mbox, 7 };
|
||||
Domain ccp2tx { powers, "ccp2tx", mbox, 8 };
|
||||
};
|
@ -1,133 +0,0 @@
|
||||
/*
|
||||
* \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 <base/stdint.h>
|
||||
|
||||
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_ */
|
@ -1,209 +0,0 @@
|
||||
/*
|
||||
* \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 _SRC__DRIVERS__PLATFORM__RPI__PROPERTY_MESSAGE_H_
|
||||
#define _SRC__DRIVERS__PLATFORM__RPI__PROPERTY_MESSAGE_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/misc_math.h>
|
||||
#include <util/construct_at.h>
|
||||
#include <base/log.h>
|
||||
|
||||
/* board-specific includes */
|
||||
#include <drivers/defs/rpi.h>
|
||||
|
||||
namespace Driver {
|
||||
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 Driver::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 <typename TAG>
|
||||
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 <typename T>
|
||||
static size_t response_size(typename T::Response *)
|
||||
{
|
||||
return sizeof(typename T::Response);
|
||||
}
|
||||
|
||||
template <typename>
|
||||
static size_t response_size(...)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static size_t request_size(typename T::Request *)
|
||||
{
|
||||
return sizeof(typename T::Request);
|
||||
}
|
||||
|
||||
template <typename>
|
||||
static size_t request_size(...)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename T, typename... ARGS>
|
||||
void construct_request(typename T::Request *, ARGS... args)
|
||||
{
|
||||
construct_at<typename T::Request>(payload, args...);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void construct_response(typename T::Response *)
|
||||
{
|
||||
construct_at<typename T::Response>(payload);
|
||||
}
|
||||
|
||||
template <typename>
|
||||
void construct_response(...) { }
|
||||
|
||||
static constexpr size_t payload_size()
|
||||
{
|
||||
return max(request_size<TAG>(0), response_size<TAG>(0));
|
||||
}
|
||||
|
||||
template <typename... REQUEST_ARGS>
|
||||
Tag(REQUEST_ARGS... request_args)
|
||||
:
|
||||
opcode(TAG::opcode()),
|
||||
buf_size(payload_size()),
|
||||
len(request_size<TAG>(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<TAG>(0);
|
||||
construct_request<TAG>(0, request_args...);
|
||||
}
|
||||
};
|
||||
|
||||
void reset()
|
||||
{
|
||||
buf_size = 0;
|
||||
code = REQUEST;
|
||||
}
|
||||
|
||||
/**
|
||||
* \return reference to tag in the message buffer
|
||||
*/
|
||||
template <typename POLICY, typename... REQUEST_ARGS>
|
||||
typename POLICY::Response const &append(REQUEST_ARGS... request_args)
|
||||
{
|
||||
auto *tag = construct_at<Tag<POLICY> >(buffer + buf_size, request_args...);
|
||||
|
||||
buf_size += sizeof(Tag<POLICY>) + Tag<POLICY>::payload_size();
|
||||
|
||||
return *(typename POLICY::Response *)tag->payload;
|
||||
}
|
||||
|
||||
template <typename POLICY, typename... REQUEST_ARGS>
|
||||
void append_no_response(REQUEST_ARGS... request_args)
|
||||
{
|
||||
construct_at<Tag<POLICY> >(buffer + buf_size, request_args...);
|
||||
|
||||
buf_size += sizeof(Tag<POLICY>) + Tag<POLICY>::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;
|
||||
log(label, " message:");
|
||||
for (unsigned i = 0;; i++) {
|
||||
for (unsigned j = 0; j < 8; j++) {
|
||||
unsigned const msg_word_idx = i*8 + j;
|
||||
log(" ", Hex(buf[msg_word_idx]));
|
||||
if (msg_word_idx*sizeof(unsigned) < buf_size)
|
||||
continue;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _SRC__DRIVERS__PLATFORM__RPI__PROPERTY_MESSAGE_H_ */
|
@ -1,13 +0,0 @@
|
||||
TARGET = rpi_platform_drv
|
||||
REQUIRES = arm_v6
|
||||
SRC_CC = device.cc
|
||||
SRC_CC += device_component.cc
|
||||
SRC_CC += device_model_policy.cc
|
||||
SRC_CC += main.cc
|
||||
SRC_CC += session_component.cc
|
||||
SRC_CC += root.cc
|
||||
INC_DIR = $(PRG_DIR) $(REP_DIR)/src/drivers/platform
|
||||
LIBS = base
|
||||
|
||||
vpath main.cc $(PRG_DIR)
|
||||
vpath %.cc $(REP_DIR)/src/drivers/platform
|
@ -1,328 +0,0 @@
|
||||
/*
|
||||
* \brief Raspberry Pi SDHCI driver
|
||||
* \author Norman Feske
|
||||
* \author Christian Helmuth
|
||||
* \author Timo Wischer
|
||||
* \author Martin Stein
|
||||
* \date 2014-09-21
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014-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.
|
||||
*/
|
||||
|
||||
/* local includes */
|
||||
#include <driver.h>
|
||||
|
||||
using namespace Genode;
|
||||
using namespace Sd_card;
|
||||
|
||||
|
||||
Driver::Driver(Env & env, Platform::Connection & platform)
|
||||
:
|
||||
Driver_base(env.ram()),
|
||||
Platform::Device(platform),
|
||||
Platform::Device::Mmio(*static_cast<Platform::Device *>(this)),
|
||||
_env(env),
|
||||
_platform(platform)
|
||||
{
|
||||
log("SD card detected");
|
||||
log("capacity: ", _card_info.capacity_mb(), " MiB");
|
||||
}
|
||||
|
||||
|
||||
Driver::~Driver() { }
|
||||
|
||||
|
||||
void Driver::_set_and_enable_clock(unsigned divider)
|
||||
{
|
||||
Control1::access_t ctl1 = Mmio::Mmio::read<Control1>();
|
||||
Control1::Clk_freq8::set(ctl1, divider);
|
||||
Control1::Clk_freq_ms2::set(ctl1, 0);
|
||||
Control1::Clk_internal_en::set(ctl1, 1);
|
||||
Mmio::write<Control1>(ctl1);
|
||||
|
||||
try {
|
||||
wait_for(_delayer, Control1::Clk_internal_stable::Equal(1));
|
||||
} catch (Polling_timeout) {
|
||||
error("could not set internal clock");
|
||||
throw Detection_failed();
|
||||
}
|
||||
Mmio::write<Control1::Clk_en>(1);
|
||||
_delayer.usleep(10*1000);
|
||||
|
||||
/* data timeout unit exponent */
|
||||
Mmio::write<Control1::Data_tounit>(0xe);
|
||||
}
|
||||
|
||||
|
||||
Card_info Driver::_init()
|
||||
{
|
||||
/* reset host controller */
|
||||
Control1::access_t v = Mmio::read<Control1>();
|
||||
Control1::Srst_hc::set(v);
|
||||
Control1::Srst_data::set(v);
|
||||
Mmio::write<Control1>(v);
|
||||
|
||||
try {
|
||||
wait_for(_delayer, Control1::Srst_hc::Equal(0));
|
||||
} catch (Polling_timeout) {
|
||||
error("host-controller soft reset timed out");
|
||||
throw Detection_failed();
|
||||
}
|
||||
log("SDHCI version: ", Mmio::read<Host_version::Vendor>(), " "
|
||||
"(specification ", Mmio::read<Host_version::Spec>() + 1, ".0)");
|
||||
|
||||
/* Enable sd card power */
|
||||
Mmio::write<Host_ctrl>(Host_ctrl::Power::bits(1)
|
||||
| Host_ctrl::Voltage::bits(Host_ctrl::Voltage::V33));
|
||||
|
||||
/* enable interrupt status reporting */
|
||||
Mmio::write<Irpt_mask>(~0UL);
|
||||
Mmio::write<Irpt_en>(~0UL);
|
||||
|
||||
/*
|
||||
* We don't read the capability register as the BCM2835 always
|
||||
* returns all bits set to zero.
|
||||
*/
|
||||
|
||||
_set_and_enable_clock(240);
|
||||
|
||||
if (!issue_command(Go_idle_state())) {
|
||||
warning("Go_idle_state command failed");
|
||||
throw Detection_failed();
|
||||
}
|
||||
_delayer.usleep(2000);
|
||||
|
||||
if (!issue_command(Send_if_cond())) {
|
||||
warning("Send_if_cond command failed");
|
||||
throw Detection_failed();
|
||||
}
|
||||
if (Mmio::read<Resp0>() != 0x1aa) {
|
||||
error("unexpected response of Send_if_cond command");
|
||||
throw Detection_failed();
|
||||
}
|
||||
|
||||
/*
|
||||
* We need to issue the same Sd_send_op_cond command multiple
|
||||
* times. The first time, we receive the status information. On
|
||||
* subsequent attempts, the response tells us that the card is
|
||||
* busy. Usually, the command is issued twice. We give up if the
|
||||
* card is not reaching busy state after one second.
|
||||
*/
|
||||
|
||||
int i = 1000;
|
||||
for (; i > 0; --i) {
|
||||
if (!issue_command(Sd_send_op_cond(0x18000, true))) {
|
||||
warning("Sd_send_op_cond command failed");
|
||||
throw Detection_failed();
|
||||
}
|
||||
if (Ocr::Busy::get(Mmio::read<Resp0>()))
|
||||
break;
|
||||
|
||||
_delayer.usleep(1000);
|
||||
}
|
||||
if (i == 0) {
|
||||
error("Sd_send_op_cond timed out, could no power-on SD card");
|
||||
throw Detection_failed();
|
||||
}
|
||||
Card_info card_info = _detect();
|
||||
|
||||
/*
|
||||
* Switch card to use 4 data signals
|
||||
*/
|
||||
if (!issue_command(Set_bus_width(Set_bus_width::Arg::Bus_width::FOUR_BITS),
|
||||
card_info.rca())) {
|
||||
warning("Set_bus_width(FOUR_BITS) command failed");
|
||||
throw Detection_failed();
|
||||
}
|
||||
/* switch host controller to use 4 data signals */
|
||||
Control0::access_t ctl0 = Mmio::read<Control0>();
|
||||
Control0::Hctl_dwidth::set(ctl0);
|
||||
Control0::Hctl_hs_en::set(ctl0);
|
||||
Mmio::write<Control0>(ctl0);
|
||||
_delayer.usleep(10*1000);
|
||||
|
||||
/*
|
||||
* Accelerate clock, the divider is hard-coded for now.
|
||||
*
|
||||
* The Raspberry Pi report as clock of 250 MHz. According to the
|
||||
* SDHCI specification, it is possible to driver SD cards with
|
||||
* 50 MHz in high-speed mode (Hctl_hs_en).
|
||||
*/
|
||||
_set_and_enable_clock(5);
|
||||
return card_info;
|
||||
}
|
||||
|
||||
|
||||
void Driver::_set_block_count(size_t block_count)
|
||||
{
|
||||
/*
|
||||
* The 'Blksizecnt' register must be written in one step. If we
|
||||
* used subsequent writes for the 'Blkcnt' and 'Blksize' bitfields,
|
||||
* the host controller of the BCM2835 would fail to recognize any
|
||||
* but the first write operation.
|
||||
*/
|
||||
Blksizecnt::access_t v = Mmio::read<Blksizecnt>();
|
||||
Blksizecnt::Blkcnt::set(v, block_count);
|
||||
Blksizecnt::Blksize::set(v, _block_size());
|
||||
Mmio::write<Blksizecnt>(v);
|
||||
}
|
||||
|
||||
|
||||
size_t Driver::_block_to_command_address(const size_t block_number)
|
||||
{
|
||||
/* use byte position for addressing with standard cards */
|
||||
if (_card_info.version() == Csd3::Version::STANDARD_CAPACITY) {
|
||||
return block_number * _block_size();
|
||||
}
|
||||
return block_number;
|
||||
}
|
||||
|
||||
|
||||
bool Driver::_issue_command(Command_base const &command)
|
||||
{
|
||||
if (!_poll_and_wait_for<Status::Inhibit>(0)) {
|
||||
error("controller inhibits issueing commands");
|
||||
return false;
|
||||
}
|
||||
/* write command argument */
|
||||
Mmio::write<Arg1>(command.arg);
|
||||
|
||||
/* assemble command register */
|
||||
Cmdtm::access_t cmd = 0;
|
||||
Cmdtm::Index::set(cmd, command.index);
|
||||
if (command.transfer != TRANSFER_NONE) {
|
||||
|
||||
Cmdtm::Isdata::set(cmd);
|
||||
Cmdtm::Tm_blkcnt_en::set(cmd);
|
||||
Cmdtm::Tm_multi_block::set(cmd);
|
||||
|
||||
if (command.index == Read_multiple_block::INDEX ||
|
||||
command.index == Write_multiple_block::INDEX)
|
||||
{
|
||||
Cmdtm::Tm_auto_cmd_en::set(cmd, Cmdtm::Tm_auto_cmd_en::CMD12);
|
||||
}
|
||||
/* set data-direction bit depending on the command */
|
||||
bool const read = command.transfer == TRANSFER_READ;
|
||||
Cmdtm::Tm_dat_dir::set(cmd, read ? Cmdtm::Tm_dat_dir::READ
|
||||
: Cmdtm::Tm_dat_dir::WRITE);
|
||||
}
|
||||
Cmdtm::access_t rsp_type = 0;
|
||||
switch (command.rsp_type) {
|
||||
case RESPONSE_NONE: rsp_type = Cmdtm::Rsp_type::RESPONSE_NONE; break;
|
||||
case RESPONSE_136_BIT: rsp_type = Cmdtm::Rsp_type::RESPONSE_136_BIT; break;
|
||||
case RESPONSE_48_BIT: rsp_type = Cmdtm::Rsp_type::RESPONSE_48_BIT; break;
|
||||
case RESPONSE_48_BIT_WITH_BUSY: rsp_type = Cmdtm::Rsp_type::RESPONSE_48_BIT_WITH_BUSY; break;
|
||||
}
|
||||
Cmdtm::Rsp_type::set(cmd, rsp_type);
|
||||
|
||||
/* write command */
|
||||
Mmio::write<Cmdtm>(cmd);
|
||||
|
||||
if (!_poll_and_wait_for<Interrupt::Cmd_done>(1)) {
|
||||
error("command timed out");
|
||||
return false;
|
||||
}
|
||||
/* clear interrupt state */
|
||||
Mmio::write<Interrupt::Cmd_done>(1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Cid Driver::_read_cid()
|
||||
{
|
||||
Cid cid;
|
||||
cid.raw_0 = Mmio::read<Resp0_136>();
|
||||
cid.raw_1 = Mmio::read<Resp1_136>();
|
||||
cid.raw_2 = Mmio::read<Resp2_136>();
|
||||
cid.raw_3 = Mmio::read<Resp3_136>();
|
||||
return cid;
|
||||
}
|
||||
|
||||
|
||||
Csd Driver::_read_csd()
|
||||
{
|
||||
Csd csd;
|
||||
csd.csd0 = Mmio::read<Resp0_136>();
|
||||
csd.csd1 = Mmio::read<Resp1_136>();
|
||||
csd.csd2 = Mmio::read<Resp2_136>();
|
||||
csd.csd3 = Mmio::read<Resp3_136>();
|
||||
return csd;
|
||||
}
|
||||
|
||||
|
||||
void Driver::read(Block::sector_t block_number,
|
||||
size_t block_count,
|
||||
char *out_buffer,
|
||||
Block::Packet_descriptor &packet)
|
||||
{
|
||||
_set_block_count(block_count);
|
||||
|
||||
if (!issue_command(Read_multiple_block(_block_to_command_address((size_t)block_number)))) {
|
||||
error("Read_multiple_block failed");
|
||||
throw Io_error();
|
||||
}
|
||||
Data::access_t *dst = (Data::access_t *)(out_buffer);
|
||||
for (size_t i = 0; i < block_count; i++) {
|
||||
|
||||
/*
|
||||
* Check for buffer-read enable bit for each block
|
||||
*
|
||||
* According to the BCM2835 documentation, this bit is
|
||||
* reserved but it actually corresponds to the bre status
|
||||
* bit as described in the SDHCI specification.
|
||||
*/
|
||||
if (!_poll_and_wait_for<Status::Bre>(1)) {
|
||||
throw Io_error(); }
|
||||
|
||||
/* read data from sdhci buffer */
|
||||
for (size_t j = 0; j < _block_size() / sizeof(Data::access_t); j++)
|
||||
*dst++ = Mmio::read<Data>();
|
||||
}
|
||||
if (!_poll_and_wait_for<Interrupt::Data_done>(1)) {
|
||||
error("completion of read request failed");
|
||||
throw Io_error();
|
||||
}
|
||||
/* clear interrupt state */
|
||||
Mmio::write<Interrupt::Data_done>(1);
|
||||
|
||||
ack_packet(packet);
|
||||
}
|
||||
|
||||
|
||||
void Driver::write(Block::sector_t block_number,
|
||||
size_t block_count,
|
||||
char const *buffer,
|
||||
Block::Packet_descriptor &packet)
|
||||
{
|
||||
_set_block_count(block_count);
|
||||
|
||||
if (!issue_command(Write_multiple_block(_block_to_command_address((size_t)block_number)))) {
|
||||
error("Write_multiple_block failed");
|
||||
throw Io_error();
|
||||
}
|
||||
Data::access_t const *src = (Data::access_t const *)(buffer);
|
||||
for (size_t i = 0; i < block_count; i++) {
|
||||
|
||||
/* check for buffer-write enable bit for each block */
|
||||
if (!_poll_and_wait_for<Status::Bwe>(1)) {
|
||||
throw Io_error(); }
|
||||
|
||||
/* write data into sdhci buffer */
|
||||
for (size_t j = 0; j < _block_size() / sizeof(Data::access_t); j++)
|
||||
Mmio::write<Data>(*src++);
|
||||
}
|
||||
if (!_poll_and_wait_for<Interrupt::Data_done>(1)) {
|
||||
error("completion of write request failed");
|
||||
throw Io_error();
|
||||
}
|
||||
/* clear interrupt state */
|
||||
Mmio::write<Interrupt::Data_done>(1);
|
||||
|
||||
ack_packet(packet);
|
||||
}
|
@ -1,221 +0,0 @@
|
||||
/*
|
||||
* \brief Raspberry Pi SDHCI driver
|
||||
* \author Norman Feske
|
||||
* \author Timo Wischer
|
||||
* \author Martin Stein
|
||||
* \date 2014-09-21
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014-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 _DRIVER_H_
|
||||
#define _DRIVER_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <platform_session/device.h>
|
||||
#include <timer_session/connection.h>
|
||||
|
||||
/* local includes */
|
||||
#include <driver_base.h>
|
||||
|
||||
namespace Sd_card { class Driver; }
|
||||
|
||||
|
||||
class Sd_card::Driver : public Driver_base,
|
||||
private Platform::Device,
|
||||
private Platform::Device::Mmio
|
||||
{
|
||||
private:
|
||||
|
||||
struct Blksizecnt : Register<0x4, 32>
|
||||
{
|
||||
struct Blkcnt : Bitfield<16, 16> { };
|
||||
struct Blksize : Bitfield<0, 10> { };
|
||||
};
|
||||
|
||||
struct Resp0 : Register<0x10, 32> { };
|
||||
struct Resp1 : Register<0x14, 32> { };
|
||||
struct Resp2 : Register<0x18, 32> { };
|
||||
struct Resp3 : Register<0x1c, 32> { };
|
||||
|
||||
/*
|
||||
* Handle the SDHCI quirk that responses of 136-bit requests are
|
||||
* shifted by 8 bits.
|
||||
*/
|
||||
template <off_t OFFSET>
|
||||
struct Cmdresp_tpl : Register<OFFSET, 32>
|
||||
{
|
||||
struct Resp_8_24 : Register<OFFSET, 32>::template Bitfield<0, 24> { };
|
||||
struct Resp_0_8 : Register<OFFSET, 32>::template Bitfield<24, 8> { };
|
||||
};
|
||||
|
||||
struct Cmdresp0 : Cmdresp_tpl<0x10> { };
|
||||
struct Cmdresp1 : Cmdresp_tpl<0x14> { };
|
||||
struct Cmdresp2 : Cmdresp_tpl<0x18> { };
|
||||
struct Cmdresp3 : Cmdresp_tpl<0x1c> { };
|
||||
|
||||
struct Resp0_136 : Bitset_2<Cmdresp3::Resp_0_8, Cmdresp0::Resp_8_24> { };
|
||||
struct Resp1_136 : Bitset_2<Cmdresp0::Resp_0_8, Cmdresp1::Resp_8_24> { };
|
||||
struct Resp2_136 : Bitset_2<Cmdresp1::Resp_0_8, Cmdresp2::Resp_8_24> { };
|
||||
struct Resp3_136 : Bitset_2<Cmdresp2::Resp_0_8, Cmdresp3::Resp_8_24> { };
|
||||
|
||||
struct Data : Register<0x20, 32> { };
|
||||
|
||||
struct Control0 : Register<0x28, 32>
|
||||
{
|
||||
struct Hctl_dwidth : Bitfield<1, 1> { };
|
||||
struct Hctl_hs_en : Bitfield<2, 1> { };
|
||||
};
|
||||
|
||||
struct Control1 : Register<0x2c, 32>
|
||||
{
|
||||
struct Clk_internal_en : Bitfield<0, 1> { };
|
||||
struct Clk_internal_stable : Bitfield<1, 1> { };
|
||||
struct Clk_en : Bitfield<2, 1> { };
|
||||
|
||||
struct Clk_freq8 : Bitfield<8, 8> { };
|
||||
struct Clk_freq_ms2 : Bitfield<6, 2> { };
|
||||
struct Data_tounit : Bitfield<16, 4> { };
|
||||
struct Srst_hc : Bitfield<24, 1> { };
|
||||
struct Srst_cmd : Bitfield<25, 1> { };
|
||||
struct Srst_data : Bitfield<26, 1> { };
|
||||
};
|
||||
|
||||
struct Status : Register<0x24, 32>
|
||||
{
|
||||
struct Inhibit : Bitfield<0, 2> { };
|
||||
struct Bwe : Bitfield<10, 1> { };
|
||||
struct Bre : Bitfield<11, 1> { };
|
||||
};
|
||||
|
||||
struct Host_ctrl : Register<0x28, 32>
|
||||
{
|
||||
struct Voltage : Bitfield<9, 3> {
|
||||
enum {
|
||||
V18 = 0b101,
|
||||
V30 = 0b110,
|
||||
V33 = 0b111,
|
||||
};
|
||||
};
|
||||
struct Power : Bitfield<8, 1> { };
|
||||
};
|
||||
|
||||
struct Arg1 : Register<0x8, 32> { };
|
||||
|
||||
struct Cmdtm : Register<0xc, 32>
|
||||
{
|
||||
struct Index : Bitfield<24, 6> { };
|
||||
struct Isdata : Bitfield<21, 1> { };
|
||||
struct Tm_blkcnt_en : Bitfield<1, 1> { };
|
||||
struct Tm_multi_block : Bitfield<5, 1> { };
|
||||
struct Tm_auto_cmd_en : Bitfield<2, 2>
|
||||
{
|
||||
enum { CMD12 = 1 };
|
||||
};
|
||||
struct Tm_dat_dir : Bitfield<4, 1>
|
||||
{
|
||||
enum { WRITE = 0, READ = 1 };
|
||||
};
|
||||
struct Rsp_type : Bitfield<16, 2>
|
||||
{
|
||||
enum Response { RESPONSE_NONE = 0,
|
||||
RESPONSE_136_BIT = 1,
|
||||
RESPONSE_48_BIT = 2,
|
||||
RESPONSE_48_BIT_WITH_BUSY = 3 };
|
||||
};
|
||||
};
|
||||
|
||||
struct Interrupt : Register<0x30, 32>
|
||||
{
|
||||
struct Cmd_done : Bitfield<0, 1> { };
|
||||
struct Data_done : Bitfield<1, 1> { };
|
||||
};
|
||||
|
||||
struct Irpt_mask : Register<0x34, 32> { };
|
||||
struct Irpt_en : Register<0x38, 32> { };
|
||||
|
||||
struct Capabilities : Register<0x40, 32> { };
|
||||
|
||||
struct Host_version : Register<0xFE, 16>
|
||||
{
|
||||
struct Spec : Bitfield<0, 8> { };
|
||||
struct Vendor : Bitfield<8, 8> { };
|
||||
};
|
||||
|
||||
struct Timer_delayer : Timer::Connection, Mmio::Delayer
|
||||
{
|
||||
Timer_delayer(Genode::Env &env) : Timer::Connection(env) { }
|
||||
|
||||
void usleep(uint64_t us) override { Timer::Connection::usleep(us); }
|
||||
};
|
||||
|
||||
Env & _env;
|
||||
Platform::Connection & _platform;
|
||||
Timer_delayer _delayer { _env };
|
||||
Platform::Device::Irq _irq { *this };
|
||||
Card_info _card_info { _init() };
|
||||
|
||||
template <typename REG>
|
||||
bool _poll_and_wait_for(unsigned value)
|
||||
{
|
||||
/* poll for a while */
|
||||
try { wait_for(Attempts(5000), Microseconds(0), _delayer,
|
||||
typename REG::Equal(value)); }
|
||||
catch (Polling_timeout) {
|
||||
|
||||
/* if the value was not reached while polling, start sleeping */
|
||||
try { wait_for(_delayer, typename REG::Equal(value)); }
|
||||
catch (Polling_timeout) { return false; }
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Card_info _init();
|
||||
void _set_and_enable_clock(unsigned divider);
|
||||
void _set_block_count(size_t block_count);
|
||||
size_t _block_to_command_address(size_t block_number);
|
||||
|
||||
|
||||
/*********************
|
||||
** Host_controller **
|
||||
*********************/
|
||||
|
||||
bool _issue_command(Command_base const &command) override;
|
||||
Cid _read_cid() override;
|
||||
Csd _read_csd() override;
|
||||
|
||||
Card_info card_info() const override { return _card_info; }
|
||||
|
||||
unsigned _read_rca() override {
|
||||
return Send_relative_addr::Response::Rca::get(Mmio::read<Resp0>()); }
|
||||
|
||||
public:
|
||||
|
||||
Driver(Env & env, Platform::Connection & platform);
|
||||
~Driver();
|
||||
|
||||
|
||||
/*******************
|
||||
** Block::Driver **
|
||||
*******************/
|
||||
|
||||
void read(Block::sector_t block_number,
|
||||
size_t block_count,
|
||||
char *buffer,
|
||||
Block::Packet_descriptor &packet) override;
|
||||
|
||||
void write(Block::sector_t block_number,
|
||||
size_t block_count,
|
||||
char const *buffer,
|
||||
Block::Packet_descriptor &packet) override;
|
||||
|
||||
Ram_dataspace_capability alloc_dma_buffer(size_t size, Cache cache) override {
|
||||
return _env.ram().alloc(size, cache); }
|
||||
};
|
||||
|
||||
#endif /* _DRIVER_H_ */
|
@ -1,4 +0,0 @@
|
||||
TARGET = rpi_sd_card_drv
|
||||
REQUIRES = arm_v6
|
||||
|
||||
include $(REP_DIR)/src/drivers/sd_card/target.inc
|
Loading…
x
Reference in New Issue
Block a user