rpi: remove drivers for platform, fb and sd_card

Fix #4396
This commit is contained in:
Stefan Kalkowski 2022-01-28 13:19:18 +01:00 committed by Norman Feske
parent 00f7819623
commit c99ca21649
42 changed files with 0 additions and 2490 deletions

View File

@ -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_ */

View File

@ -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
}

View File

@ -1,3 +0,0 @@
Device drivers needed to run interactive
scenarios on Raspberry Pi 1

View File

@ -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

View File

@ -1 +0,0 @@
2022-01-18 ae83537a60f37a586d1744066b8e04439e469191

View File

@ -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/$@ $@

View File

@ -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>

View File

@ -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>

View File

@ -1 +0,0 @@
<config width="1024" height="768" buffered="yes"/>

View File

@ -1 +0,0 @@
2022-01-18 fc7a148586797692c9b5118b4f9feb15977d1fff

View File

@ -1,3 +0,0 @@
Device drivers needed for scenarios
using one network interface

View File

@ -1,4 +0,0 @@
_/src/platform_drv
_/src/usb_host_drv
_/src/usb_net_drv
_/raw/drivers_nic-rpi

View File

@ -1 +0,0 @@
2022-01-18 7d8af3ec212054217e19c0ae9f8e05b620a674a3

View File

@ -1,4 +0,0 @@
content: drivers.config
drivers.config:
cp $(REP_DIR)/recipes/raw/drivers_nic-rpi/$@ $@

View File

@ -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>

View File

@ -1 +0,0 @@
2022-01-18 48c889fe114b5c7932fa584ac40b084a3ce6deff

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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

View File

@ -1,2 +0,0 @@
SRC_DIR = src/drivers/framebuffer/rpi
include $(GENODE_DIR)/repos/base/recipes/src/content.inc

View File

@ -1 +0,0 @@
2022-01-18 f69b1ff68fa854cc95c624efd275c4efc53018f1

View File

@ -1,5 +0,0 @@
base
os
blit
platform_session
capture_session

View File

@ -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.

View File

@ -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);
}

View File

@ -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)

View File

@ -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_ */

View File

@ -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);
}

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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

View File

@ -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); }

View File

@ -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_ */

View File

@ -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 };
};

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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

View File

@ -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);
}

View File

@ -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_ */

View File

@ -1,4 +0,0 @@
TARGET = rpi_sd_card_drv
REQUIRES = arm_v6
include $(REP_DIR)/src/drivers/sd_card/target.inc