os: use async IRQ and server lib in drivers

Use the new asynchronous IRQ interface in the mostly used drivers, e.g.:

* ahci_drv: x86/exynos5
* gpio_drv: imx53/omap4
* input_drv: imx53/dummy
* ps2_drv: x86/pl050
* timer_drv

Now, the Irq_session is requested from Gpio::Session:

From now on we use an asynchronous IRQ interface. To prevent triggering
another GPIO IRQ while currently handling the former one, IRQs must
now by acknowledged explicitly. While here, we also changed the GPIO
session interface regarding IRQ management. The generic GPIO component
now wraps the Irq_session managed by the backend instead of using the
GPIO backend methods directly. A client using the GPIO session may
request the Irq_session_capability by calling
'Gpio::Session::irq_session()' and can use this capability when using
a local Irq_session_client.

Issue #1456.
This commit is contained in:
Josef Söntgen 2015-04-14 13:56:26 +02:00 committed by Christian Helmuth
parent bfb47cfd4e
commit 85599c072f
53 changed files with 1114 additions and 758 deletions

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (C) 2011-2013 Genode Labs GmbH * Copyright (C) 2011-2015 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
@ -30,39 +30,62 @@ class Gpio::Session_component : public Genode::Rpc_object<Gpio::Session>
{ {
private: private:
Driver &_driver; struct Irq_session_component : public Genode::Rpc_object<Genode::Irq_session>
unsigned long _pin; {
Genode::Signal_context_capability _sigh; Driver &_driver;
unsigned long _pin;
Irq_session_component(Driver &driver, unsigned long pin)
: _driver(driver), _pin(pin) { }
/***************************
** Irq_session interface **
***************************/
void ack_irq() override { _driver.ack_irq(_pin); }
void sigh(Genode::Signal_context_capability sigh) override {
_driver.register_signal(_pin, sigh); }
};
Genode::Rpc_entrypoint &_ep;
Driver &_driver;
unsigned long _pin;
Irq_session_component _irq_component;
Genode::Irq_session_capability _irq_cap;
public: public:
Session_component(Driver &driver, unsigned long gpio_pin) Session_component(Genode::Rpc_entrypoint &ep,
: _driver(driver), _pin(gpio_pin) { } Driver &driver,
unsigned long gpio_pin)
: _ep(ep), _driver(driver), _pin(gpio_pin),
_irq_component(_driver, _pin),
_irq_cap(_ep.manage(&_irq_component)) { }
~Session_component() ~Session_component() { _ep.dissolve(&_irq_component); }
{
if (_sigh.valid())
_driver.unregister_signal(_pin);
}
/************************************
/*****************************
** Gpio::Session interface ** ** Gpio::Session interface **
************************************/ *****************************/
void direction(Direction d) { _driver.direction(_pin, (d == IN)); } void direction(Direction d) { _driver.direction(_pin, (d == IN)); }
void write(bool level) { _driver.write(_pin, level); } void write(bool level) { _driver.write(_pin, level); }
bool read() { return _driver.read(_pin); } bool read() { return _driver.read(_pin); }
void irq_enable(bool enable) { _driver.irq_enable(_pin, enable); }
void irq_sigh(Genode::Signal_context_capability cap) void debouncing(unsigned int us)
{ {
if (cap.valid()) { if (us) {
_sigh = cap; _driver.debounce_time(_pin, us);
_driver.register_signal(_pin, cap); _driver.debounce_enable(_pin, true);
} } else
_driver.debounce_enable(_pin, false);
} }
void irq_type(Irq_type type) Genode::Irq_session_capability irq_session(Irq_type type)
{ {
switch (type) { switch (type) {
case HIGH_LEVEL: case HIGH_LEVEL:
@ -77,15 +100,10 @@ class Gpio::Session_component : public Genode::Rpc_object<Gpio::Session>
case FALLING_EDGE: case FALLING_EDGE:
_driver.falling_detect(_pin); _driver.falling_detect(_pin);
}; };
}
void debouncing(unsigned int us) _driver.irq_enable(_pin, true);
{
if (us) { return _irq_cap;
_driver.debounce_time(_pin, us);
_driver.debounce_enable(_pin, true);
} else
_driver.debounce_enable(_pin, false);
} }
}; };
@ -94,7 +112,8 @@ class Gpio::Root : public Genode::Root_component<Gpio::Session_component>
{ {
private: private:
Driver &_driver; Genode::Rpc_entrypoint &_ep;
Driver &_driver;
protected: protected:
@ -114,7 +133,7 @@ class Gpio::Root : public Genode::Root_component<Gpio::Session_component>
throw Genode::Root::Quota_exceeded(); throw Genode::Root::Quota_exceeded();
} }
return new (md_alloc()) Session_component(_driver, pin); return new (md_alloc()) Session_component(_ep, _driver, pin);
} }
public: public:
@ -122,7 +141,7 @@ class Gpio::Root : public Genode::Root_component<Gpio::Session_component>
Root(Genode::Rpc_entrypoint *session_ep, Root(Genode::Rpc_entrypoint *session_ep,
Genode::Allocator *md_alloc, Driver &driver) Genode::Allocator *md_alloc, Driver &driver)
: Genode::Root_component<Gpio::Session_component>(session_ep, md_alloc), : Genode::Root_component<Gpio::Session_component>(session_ep, md_alloc),
_driver(driver) { } _ep(*session_ep), _driver(driver) { }
}; };

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (C) 2011-2013 Genode Labs GmbH * Copyright (C) 2011-2015 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
@ -92,6 +92,13 @@ struct Gpio::Driver
*/ */
virtual void irq_enable(unsigned gpio, bool enable) = 0; virtual void irq_enable(unsigned gpio, bool enable) = 0;
/**
* Acknowledge IRQ for specified GPIO pin
*
* \param gpio corresponding gpio pin number
*/
virtual void ack_irq(unsigned gpio) = 0;
/** /**
* Register signal handler for interrupts * Register signal handler for interrupts
* *

View File

@ -7,7 +7,7 @@
/* /*
* Copyright (C) 2012 Ksys Labs LLC * Copyright (C) 2012 Ksys Labs LLC
* Copyright (C) 2012-2013 Genode Labs GmbH * Copyright (C) 2012-2015 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
@ -27,15 +27,13 @@ struct Gpio::Session_client : Genode::Rpc_client<Session>
explicit Session_client(Session_capability session) explicit Session_client(Session_capability session)
: Genode::Rpc_client<Session>(session) { } : Genode::Rpc_client<Session>(session) { }
void direction(Direction d) override { call<Rpc_direction>(d); } void direction(Direction d) override { call<Rpc_direction>(d); }
void write(bool level) override { call<Rpc_write>(level); } void write(bool level) override { call<Rpc_write>(level); }
bool read() override { return call<Rpc_read>(); } bool read() override { return call<Rpc_read>(); }
void debouncing(unsigned int us) override { call<Rpc_debouncing>(us); } void debouncing(unsigned int us) override { call<Rpc_debouncing>(us); }
void irq_type(Irq_type it) override { call<Rpc_irq_type>(it); }
void irq_enable(bool enable) override { call<Rpc_irq_enable>(enable); }
void irq_sigh(Genode::Signal_context_capability cap) override { Genode::Irq_session_capability irq_session(Irq_type type) override {
call<Rpc_irq_sigh>(cap); } return call<Rpc_irq_session>(type); }
}; };
#endif /* _INCLUDE__GPIO_SESSION_H__CLIENT_H_ */ #endif /* _INCLUDE__GPIO_SESSION_H__CLIENT_H_ */

View File

@ -7,7 +7,7 @@
/* /*
* Copyright (C) 2012 Ksys Labs LLC * Copyright (C) 2012 Ksys Labs LLC
* Copyright (C) 2012-2013 Genode Labs GmbH * Copyright (C) 2012-2015 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
@ -19,6 +19,7 @@
#include <base/signal.h> #include <base/signal.h>
#include <dataspace/capability.h> #include <dataspace/capability.h>
#include <session/session.h> #include <session/session.h>
#include <irq_session/capability.h>
namespace Gpio { struct Session; } namespace Gpio { struct Session; }
@ -62,42 +63,26 @@ struct Gpio::Session : Genode::Session
virtual void debouncing(unsigned int us) = 0; virtual void debouncing(unsigned int us) = 0;
/** /**
* Configure the type of interrupt for the GPIO pin * Rquest IRQ session
* *
* \param it type of IRQ * \param type type of IRQ
*/ */
virtual void irq_type(Irq_type it) = 0; virtual Genode::Irq_session_capability irq_session(Irq_type type) = 0;
/**
* Enable or disable the interrupt of the GPIO pin
*
* \param enable interrupt status( true - enable, false - disable)
*/
virtual void irq_enable(bool enable) = 0;
/**
* Register signal handler to be notified on interrupt
*
* \param cap capability of signal-context to handle GPIO interrupt
*/
virtual void irq_sigh(Genode::Signal_context_capability cap) = 0;
/******************* /*******************
** RPC interface ** ** RPC interface **
*******************/ *******************/
GENODE_RPC(Rpc_direction, void, direction, Direction); GENODE_RPC(Rpc_direction, void, direction, Direction);
GENODE_RPC(Rpc_write, void, write, bool); GENODE_RPC(Rpc_write, void, write, bool);
GENODE_RPC(Rpc_read, bool, read); GENODE_RPC(Rpc_read, bool, read);
GENODE_RPC(Rpc_debouncing, void, debouncing, unsigned int); GENODE_RPC(Rpc_debouncing, void, debouncing, unsigned int);
GENODE_RPC(Rpc_irq_type, void, irq_type, Irq_type); GENODE_RPC(Rpc_irq_session, Genode::Irq_session_capability,
GENODE_RPC(Rpc_irq_enable, void, irq_enable, bool); irq_session, Irq_type);
GENODE_RPC(Rpc_irq_sigh, void, irq_sigh, Genode::Signal_context_capability);
GENODE_RPC_INTERFACE(Rpc_direction, Rpc_write, Rpc_read, GENODE_RPC_INTERFACE(Rpc_direction, Rpc_write, Rpc_read,
Rpc_debouncing, Rpc_irq_type, Rpc_irq_enable, Rpc_debouncing, Rpc_irq_session);
Rpc_irq_sigh);
}; };
#endif /* _INCLUDE__GPIO_SESSION__GPIO_SESSION_H_ */ #endif /* _INCLUDE__GPIO_SESSION__GPIO_SESSION_H_ */

View File

@ -1,5 +1,5 @@
SRC_CC += main.cc SRC_CC += main.cc
LIBS += base alarm LIBS += base alarm server
INC_DIR += $(REP_DIR)/src/drivers/timer/include INC_DIR += $(REP_DIR)/src/drivers/timer/include
vpath main.cc $(REP_DIR)/src/drivers/timer vpath main.cc $(REP_DIR)/src/drivers/timer

View File

@ -902,6 +902,8 @@ struct Sata_ahci : Attached_mmio
/* port 0 settings */ /* port 0 settings */
unsigned p0_speed; unsigned p0_speed;
Irq_connection p0_irq; Irq_connection p0_irq;
Genode::Signal_receiver p0_irq_rec;
Genode::Signal_context p0_irq_ctx;
enum { SATA_3_MAX_SPEED = 3 }; enum { SATA_3_MAX_SPEED = 3 };
@ -922,7 +924,10 @@ struct Sata_ahci : Attached_mmio
dbc_stable_trials(5), dbc_stable_trials(5),
p0_speed(SATA_3_MAX_SPEED), p0_speed(SATA_3_MAX_SPEED),
p0_irq(Genode::Board_base::SATA_IRQ) p0_irq(Genode::Board_base::SATA_IRQ)
{ } {
p0_irq.sigh(p0_irq_rec.manage(&p0_irq_ctx));
p0_irq.ack_irq();
}
/** /**
* Clear all interrupts at port 0 * Clear all interrupts at port 0
@ -1145,7 +1150,7 @@ struct Sata_ahci : Attached_mmio
{ {
typedef typename P0IS_BIT::Bitfield_base P0is_bit; typedef typename P0IS_BIT::Bitfield_base P0is_bit;
write<P0ci>(1 << tag); write<P0ci>(1 << tag);
p0_irq.wait_for_irq(); p0_irq_rec.wait_for_signal();
if (!read<Is::Ips>()) { if (!read<Is::Ips>()) {
PERR("ATA0 no IRQ raised"); PERR("ATA0 no IRQ raised");
return -1; return -1;
@ -1269,6 +1274,7 @@ struct Sata_ahci : Attached_mmio
printf("ATA0 supports UDMA-133 and NCQ with queue depth %u\n", printf("ATA0 supports UDMA-133 and NCQ with queue depth %u\n",
dev_id->queue_depth + 1); dev_id->queue_depth + 1);
write<Is::Ips>(1); write<Is::Ips>(1);
p0_irq.ack_irq();
/* destroy receive buffer DMA */ /* destroy receive buffer DMA */
env()->rm_session()->detach(dev_id_virt); env()->rm_session()->detach(dev_id_virt);
@ -1300,6 +1306,7 @@ struct Sata_ahci : Attached_mmio
/* end command */ /* end command */
write<Is::Ips>(1); write<Is::Ips>(1);
p0_irq.ack_irq();
/* check for hidden blocks */ /* check for hidden blocks */
return max_native_addr + 1 != block_cnt; return max_native_addr + 1 != block_cnt;
@ -1344,6 +1351,7 @@ struct Sata_ahci : Attached_mmio
} }
/* end command */ /* end command */
write<Is::Ips>(1); write<Is::Ips>(1);
p0_irq.ack_irq();
return 0; return 0;
} }
@ -1668,7 +1676,7 @@ struct Sata_ahci : Attached_mmio
/* issue command and wait for completion */ /* issue command and wait for completion */
write<P0sact>(1 << tag); write<P0sact>(1 << tag);
write<P0ci>(1 << tag); write<P0ci>(1 << tag);
p0_irq.wait_for_irq(); p0_irq_rec.wait_for_signal();
/* get port back ready and deteremine command state */ /* get port back ready and deteremine command state */
int ret = p0_handle_irqs(lba); int ret = p0_handle_irqs(lba);
@ -1684,6 +1692,7 @@ struct Sata_ahci : Attached_mmio
return -1; return -1;
} }
write<Is::Ips>(1); write<Is::Ips>(1);
p0_irq.ack_irq();
} }
return ret; return ret;
} }

View File

@ -370,6 +370,8 @@ class Ahci_device_base
Generic_ctrl *_ctrl; /* generic host control */ Generic_ctrl *_ctrl; /* generic host control */
Ahci_port *_port; /* port base of device */ Ahci_port *_port; /* port base of device */
Irq_connection *_irq; /* device IRQ */ Irq_connection *_irq; /* device IRQ */
Genode::Signal_receiver _irq_rec; /* IRQ signal receiver */
Genode::Signal_context _irq_ctx; /* IRQ signal context */
size_t _block_cnt; /* number of blocks on device */ size_t _block_cnt; /* number of blocks on device */
Command_list *_cmd_list; /* pointer to command list */ Command_list *_cmd_list; /* pointer to command list */
Command_table *_cmd_table; /* pointer to command table */ Command_table *_cmd_table; /* pointer to command table */
@ -453,7 +455,7 @@ class Ahci_device_base
while (!status) { while (!status) {
/* wait for interrupt */ /* wait for interrupt */
_irq->wait_for_irq(); _irq_rec.wait_for_signal();
if (verbose) if (verbose)
PDBG("Int status (IRQ): global: %x port: %x error: %x", PDBG("Int status (IRQ): global: %x port: %x error: %x",
@ -479,6 +481,8 @@ class Ahci_device_base
/* acknowledge global port interrupt */ /* acknowledge global port interrupt */
_ctrl->hba_interrupt_ack(); _ctrl->hba_interrupt_ack();
_irq->ack_irq();
/* disable hba */ /* disable hba */
_port->hba_disable(); _port->hba_disable();
} }

View File

@ -184,6 +184,10 @@ class Ahci_device : public Ahci_device_base
_disable_msi(pci_device); _disable_msi(pci_device);
device->_irq = new(env()->heap()) Irq_connection(intr & 0xff); device->_irq = new(env()->heap()) Irq_connection(intr & 0xff);
Genode::Signal_context_capability cap = device->_irq_rec.manage(&device->_irq_ctx);
device->_irq->sigh(cap);
device->_irq->ack_irq();
/* remember pci_device to be able to allocate ram memory which is dma able */ /* remember pci_device to be able to allocate ram memory which is dma able */
device->_pci_device_cap = device_cap; device->_pci_device_cap = device_cap;
device->_pci_device = pci_device; device->_pci_device = pci_device;

View File

@ -113,7 +113,19 @@ class I2c_interface : public Attached_mmio
TX_DELAY_US = 1, TX_DELAY_US = 1,
}; };
Irq_connection _irq; Irq_connection _irq;
Genode::Signal_receiver _irq_rec;
Genode::Signal_context _irq_ctx;
/**
* Wait until the IRQ signal was received
*/
void _wait_for_irq()
{
_irq_rec.wait_for_signal();
_irq.ack_irq();
}
/** /**
* Stop a running transfer as master * Stop a running transfer as master
@ -166,7 +178,7 @@ class I2c_interface : public Attached_mmio
write<Con>(con); write<Con>(con);
Stat::Busy::set(stat, 1); Stat::Busy::set(stat, 1);
write<Stat>(stat); write<Stat>(stat);
_irq.wait_for_irq(); _wait_for_irq();
if (_arbitration_error()) return -1; if (_arbitration_error()) return -1;
return 0; return 0;
} }
@ -196,6 +208,7 @@ class I2c_interface : public Attached_mmio
return 0; return 0;
} }
public: public:
/** /**
@ -224,8 +237,13 @@ class I2c_interface : public Attached_mmio
Lc::Sda_out_delay::set(lc, 2); Lc::Sda_out_delay::set(lc, 2);
Lc::Filter_en::set(lc, 1); Lc::Filter_en::set(lc, 1);
write<Lc>(lc); write<Lc>(lc);
_irq.sigh(_irq_rec.manage(&_irq_ctx));
_irq.ack_irq();
} }
~I2c_interface() { _irq_rec.dissolve(&_irq_ctx); }
/** /**
* Transmit an I2C message as master * Transmit an I2C message as master
* *
@ -252,7 +270,7 @@ class I2c_interface : public Attached_mmio
/* finish last byte and prepare for next one */ /* finish last byte and prepare for next one */
off++; off++;
write<Con::Irq_pending>(0); write<Con::Irq_pending>(0);
_irq.wait_for_irq(); _wait_for_irq();
if (_arbitration_error()) return -1; if (_arbitration_error()) return -1;
} }
/* end message transfer */ /* end message transfer */
@ -285,7 +303,7 @@ class I2c_interface : public Attached_mmio
while (1) while (1)
{ {
/* receive next message byte */ /* receive next message byte */
_irq.wait_for_irq(); _wait_for_irq();
if (_arbitration_error()) return -1; if (_arbitration_error()) return -1;
buf[off] = read<Ds>(); buf[off] = read<Ds>();
off++; off++;
@ -619,14 +637,6 @@ class I2c_hdmi : public I2c_interface
} }
}; };
/**
* Return singleton of device instance
*/
static I2c_hdmi * i2c_hdmi()
{
static I2c_hdmi s;
return &s;
}
/** /**
* Converts input stream from video mixer into HDMI packet stream for HDMI PHY * Converts input stream from video mixer into HDMI packet stream for HDMI PHY
@ -942,12 +952,15 @@ class Hdmi : public Attached_mmio
write<Fp_3d::Value>(0); write<Fp_3d::Value>(0);
} }
I2c_hdmi _i2c_hdmi;
public: public:
/** /**
* Constructor * Constructor
*/ */
Hdmi() : Attached_mmio(0x14530000, 0xa0000) { } Hdmi()
: Attached_mmio(0x14530000, 0xa0000), _i2c_hdmi() { }
/** /**
* Initialize HDMI controller for video output only * Initialize HDMI controller for video output only
@ -978,12 +991,12 @@ class Hdmi : public Attached_mmio
} }
/* set-up HDMI PHY */ /* set-up HDMI PHY */
write<Phy_con_0::Pwr_off>(0); write<Phy_con_0::Pwr_off>(0);
if (i2c_hdmi()->stop_hdmi_phy()) return -1; if (_i2c_hdmi.stop_hdmi_phy()) return -1;
write<Phy_rstout::Reset>(1); write<Phy_rstout::Reset>(1);
delayer()->usleep(10000); delayer()->usleep(10000);
write<Phy_rstout::Reset>(0); write<Phy_rstout::Reset>(0);
delayer()->usleep(10000); delayer()->usleep(10000);
if (i2c_hdmi()->setup_and_start_hdmi_phy(pixel_clk)) return -1; if (_i2c_hdmi.setup_and_start_hdmi_phy(pixel_clk)) return -1;
/* reset HDMI CORE */ /* reset HDMI CORE */
write<Core_rstout::Reset>(0); write<Core_rstout::Reset>(0);
@ -1095,15 +1108,6 @@ class Hdmi : public Attached_mmio
} }
}; };
/**
* Return singleton of device instance
*/
static Hdmi * hdmi()
{
static Hdmi s;
return &s;
}
/************************* /*************************
** Framebuffer::Driver ** ** Framebuffer::Driver **
@ -1140,7 +1144,8 @@ int Framebuffer::Driver::_init_hdmi(addr_t fb_phys)
if (err) { return -1; } if (err) { return -1; }
/* set-up HDMI to feed connected device */ /* set-up HDMI to feed connected device */
err = hdmi()->init_hdmi(_fb_width, _fb_height); static Hdmi hdmi;
err = hdmi.init_hdmi(_fb_width, _fb_height);
if (err) { return -1; } if (err) { return -1; }
return 0; return 0;
} }

View File

@ -17,6 +17,7 @@
/* Genode includes */ /* Genode includes */
#include <base/stdint.h> #include <base/stdint.h>
#include <base/printf.h> #include <base/printf.h>
#include <os/server.h>
namespace Framebuffer namespace Framebuffer
{ {

View File

@ -11,9 +11,6 @@
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
*/ */
/* local includes */
#include <driver.h>
/* Genode includes */ /* Genode includes */
#include <framebuffer_session/framebuffer_session.h> #include <framebuffer_session/framebuffer_session.h>
#include <cap_session/connection.h> #include <cap_session/connection.h>
@ -22,6 +19,10 @@
#include <base/sleep.h> #include <base/sleep.h>
#include <os/config.h> #include <os/config.h>
#include <os/static_root.h> #include <os/static_root.h>
#include <os/server.h>
/* local includes */
#include <driver.h>
namespace Framebuffer namespace Framebuffer
{ {
@ -111,47 +112,52 @@ class Framebuffer::Session_component
}; };
/** struct Main
* Program entrypoint
*/
int main(int, char **)
{ {
using namespace Framebuffer; Server::Entrypoint &ep;
Framebuffer::Driver driver;
/* default config */ Main(Server::Entrypoint &ep)
size_t width = 1920; : ep(ep), driver()
size_t height = 1080; {
Driver::Output output = Driver::OUTPUT_HDMI; using namespace Framebuffer;
/* try to read custom user config */ /* default config */
try { size_t width = 1920;
char out[5] = { }; size_t height = 1080;
Genode::Xml_node config_node = Genode::config()->xml_node(); Driver::Output output = Driver::OUTPUT_HDMI;
config_node.attribute("width").value(&width);
config_node.attribute("height").value(&height); /* try to read custom user config */
config_node.attribute("output").value(out, sizeof(out)); try {
if (!Genode::strcmp(out, "LCD")) { char out[5] = { 0 };
output = Driver::OUTPUT_LCD; Genode::Xml_node config_node = Genode::config()->xml_node();
config_node.attribute("width").value(&width);
config_node.attribute("height").value(&height);
config_node.attribute("output").value(out, sizeof(out));
if (!Genode::strcmp(out, "LCD")) {
output = Driver::OUTPUT_LCD;
}
} }
catch (...) {
PDBG("using default configuration: HDMI@%dx%d", width, height);
}
/* let entrypoint serve the framebuffer session and root interfaces */
static Session_component fb_session(driver, width, height, output);
static Static_root<Framebuffer::Session> fb_root(ep.manage(fb_session));
/* announce service and relax */
env()->parent()->announce(ep.manage(fb_root));
} }
catch (...) { };
PDBG("using default configuration: HDMI@%dx%d", width, height);
}
/* create server backend */
static Driver driver;
/* create server entrypoint */
enum { STACK_SIZE = 4096 };
static Cap_connection cap;
static Rpc_entrypoint ep(&cap, STACK_SIZE, "fb_ep");
/* let entrypoint serve the framebuffer session and root interfaces */ /************
static Session_component fb_session(driver, width, height, output); ** Server **
static Static_root<Framebuffer::Session> fb_root(ep.manage(&fb_session)); ************/
/* announce service and relax */ namespace Server {
env()->parent()->announce(ep.manage(&fb_root)); char const *name() { return "fb_drv_ep"; }
sleep_forever(); size_t stack_size() { return 1024*sizeof(long); }
return 0; void construct(Entrypoint &ep) { static Main server(ep); }
} }

View File

@ -1,5 +1,5 @@
TARGET = fb_drv TARGET = fb_drv
REQUIRES = exynos5 REQUIRES = exynos5
SRC_CC += main.cc driver.cc SRC_CC += main.cc driver.cc
LIBS += base config LIBS += base config server
INC_DIR += $(PRG_DIR) INC_DIR += $(PRG_DIR)

View File

@ -22,6 +22,7 @@
#include <gpio/driver.h> #include <gpio/driver.h>
#include <irq_session/connection.h> #include <irq_session/connection.h>
#include <timer_session/connection.h> #include <timer_session/connection.h>
#include <os/server.h>
/* local includes */ /* local includes */
#include "gpio.h" #include "gpio.h"
@ -34,6 +35,7 @@ class Imx53_driver : public Gpio::Driver
private: private:
enum { enum {
PIN_SHIFT = 5,
MAX_BANKS = 7, MAX_BANKS = 7,
MAX_PINS = 32 MAX_PINS = 32
}; };
@ -52,31 +54,44 @@ class Imx53_driver : public Gpio::Driver
{ {
public: public:
void handle_irq(); void handle_irq()
{
unsigned long status = _reg.read<Gpio_reg::Int_stat>();
for(unsigned i = 0; i < MAX_PINS; i++) {
if ((status & (1 << i)) && _irq_enabled[i] &&
_sig_cap[i].valid())
Genode::Signal_transmitter(_sig_cap[i]).submit();
}
}
private: private:
class Irq_handler : public Genode::Thread<4096> class Irq_handler
{ {
private: private:
Genode::Irq_connection _irq; Genode::Irq_connection _irq;
Gpio_bank *_bank; Genode::Signal_rpc_member<Irq_handler> _dispatcher;
Gpio_bank *_bank;
void _handle(unsigned)
{
_bank->handle_irq();
_irq.ack_irq();
}
public: public:
Irq_handler(unsigned irq, Gpio_bank *bank) Irq_handler(Server::Entrypoint &ep,
: Genode::Thread<4096>("irq handler"), unsigned irq, Gpio_bank *bank)
_irq(irq), _bank(bank) { start(); } : _irq(irq), _dispatcher(ep, *this, &Irq_handler::_handle),
_bank(bank)
void entry()
{ {
while (true) { _irq.sigh(_dispatcher);
_irq.wait_for_irq(); _irq.ack_irq();
_bank->handle_irq();
}
} }
}; };
Gpio_reg _reg; Gpio_reg _reg;
@ -84,15 +99,14 @@ class Imx53_driver : public Gpio::Driver
Irq_handler _irqh_high; Irq_handler _irqh_high;
Genode::Signal_context_capability _sig_cap[MAX_PINS]; Genode::Signal_context_capability _sig_cap[MAX_PINS];
bool _irq_enabled[MAX_PINS]; bool _irq_enabled[MAX_PINS];
Genode::Lock _lock;
public: public:
Gpio_bank(Genode::addr_t base, Genode::size_t size, Gpio_bank(Server::Entrypoint &ep, Genode::addr_t base,
unsigned irq_low, unsigned irq_high) Genode::size_t size, unsigned irq_low, unsigned irq_high)
: _reg(base, size), : _reg(base, size),
_irqh_low(irq_low, this), _irqh_low(ep, irq_low, this),
_irqh_high(irq_high, this) { } _irqh_high(ep, irq_high, this) { }
Gpio_reg* regs() { return &_reg; } Gpio_reg* regs() { return &_reg; }
@ -102,20 +116,70 @@ class Imx53_driver : public Gpio::Driver
_irq_enabled[pin] = enable; _irq_enabled[pin] = enable;
} }
void ack_irq(int pin)
{
_reg.write<Gpio_reg::Int_stat>(1, pin);
}
void sigh(int pin, Genode::Signal_context_capability cap) { void sigh(int pin, Genode::Signal_context_capability cap) {
_sig_cap[pin] = cap; } _sig_cap[pin] = cap; }
}; };
Server::Entrypoint &_ep;
static Gpio_bank _gpio_bank[MAX_BANKS]; Gpio_bank _gpio_bank_0;
Gpio_bank _gpio_bank_1;
Gpio_bank _gpio_bank_2;
Gpio_bank _gpio_bank_3;
Gpio_bank _gpio_bank_4;
Gpio_bank _gpio_bank_5;
Gpio_bank _gpio_bank_6;
Gpio_bank *_gpio_bank(int gpio)
{
switch (gpio >> PIN_SHIFT) {
case 0:
return &_gpio_bank_0;
case 1:
return &_gpio_bank_1;
case 2:
return &_gpio_bank_2;
case 3:
return &_gpio_bank_3;
case 4:
return &_gpio_bank_4;
case 5:
return &_gpio_bank_5;
case 6:
return &_gpio_bank_6;
}
PERR("no Gpio_bank for pin %d available", gpio);
return 0;
}
int _gpio_bank_index(int gpio) { return gpio >> 5; }
int _gpio_index(int gpio) { return gpio & 0x1f; } int _gpio_index(int gpio) { return gpio & 0x1f; }
Imx53_driver() Imx53_driver(Server::Entrypoint &ep)
:
_ep(ep),
_gpio_bank_0(_ep, Genode::Board_base::GPIO1_MMIO_BASE, Genode::Board_base::GPIO1_MMIO_SIZE,
Genode::Board_base::GPIO1_IRQL, Genode::Board_base::GPIO1_IRQH),
_gpio_bank_1(_ep, Genode::Board_base::GPIO2_MMIO_BASE, Genode::Board_base::GPIO2_MMIO_SIZE,
Genode::Board_base::GPIO2_IRQL, Genode::Board_base::GPIO2_IRQH),
_gpio_bank_2(_ep, Genode::Board_base::GPIO3_MMIO_BASE, Genode::Board_base::GPIO3_MMIO_SIZE,
Genode::Board_base::GPIO3_IRQL, Genode::Board_base::GPIO3_IRQH),
_gpio_bank_3(_ep, Genode::Board_base::GPIO4_MMIO_BASE, Genode::Board_base::GPIO4_MMIO_SIZE,
Genode::Board_base::GPIO4_IRQL, Genode::Board_base::GPIO4_IRQH),
_gpio_bank_4(_ep, Genode::Board_base::GPIO5_MMIO_BASE, Genode::Board_base::GPIO5_MMIO_SIZE,
Genode::Board_base::GPIO5_IRQL, Genode::Board_base::GPIO5_IRQH),
_gpio_bank_5(_ep, Genode::Board_base::GPIO6_MMIO_BASE, Genode::Board_base::GPIO6_MMIO_SIZE,
Genode::Board_base::GPIO6_IRQL, Genode::Board_base::GPIO6_IRQH),
_gpio_bank_6(_ep, Genode::Board_base::GPIO7_MMIO_BASE, Genode::Board_base::GPIO7_MMIO_SIZE,
Genode::Board_base::GPIO7_IRQL, Genode::Board_base::GPIO7_IRQH)
{ {
for (unsigned i = 0; i < MAX_BANKS; ++i) { for (unsigned i = 0; i < MAX_BANKS; ++i) {
Gpio_reg *regs = _gpio_bank[i].regs(); Gpio_reg *regs = _gpio_bank(i << PIN_SHIFT)->regs();
for (unsigned j = 0; j < MAX_PINS; j++) { for (unsigned j = 0; j < MAX_PINS; j++) {
regs->write<Gpio_reg::Int_conf>(Gpio_reg::Int_conf::LOW_LEVEL, j); regs->write<Gpio_reg::Int_conf>(Gpio_reg::Int_conf::LOW_LEVEL, j);
regs->write<Gpio_reg::Int_mask>(0, j); regs->write<Gpio_reg::Int_mask>(0, j);
@ -124,10 +188,10 @@ class Imx53_driver : public Gpio::Driver
} }
} }
public: public:
static Imx53_driver& factory(); static Imx53_driver &factory(Server::Entrypoint &ep);
/****************************** /******************************
** Gpio::Driver interface ** ** Gpio::Driver interface **
@ -137,7 +201,7 @@ class Imx53_driver : public Gpio::Driver
{ {
if (verbose) PDBG("gpio=%d input=%d", gpio, input); if (verbose) PDBG("gpio=%d input=%d", gpio, input);
Gpio_reg *gpio_reg = _gpio_bank[_gpio_bank_index(gpio)].regs(); Gpio_reg *gpio_reg = _gpio_bank(gpio)->regs();
gpio_reg->write<Gpio_reg::Dir>(input ? 0 : 1, gpio_reg->write<Gpio_reg::Dir>(input ? 0 : 1,
_gpio_index(gpio)); _gpio_index(gpio));
} }
@ -146,7 +210,7 @@ class Imx53_driver : public Gpio::Driver
{ {
if (verbose) PDBG("gpio=%d level=%d", gpio, level); if (verbose) PDBG("gpio=%d level=%d", gpio, level);
Gpio_reg *gpio_reg = _gpio_bank[_gpio_bank_index(gpio)].regs(); Gpio_reg *gpio_reg = _gpio_bank(gpio)->regs();
gpio_reg->write<Gpio_reg::Data>(level ? 1 : 0, gpio_reg->write<Gpio_reg::Data>(level ? 1 : 0,
_gpio_index(gpio)); _gpio_index(gpio));
@ -156,7 +220,7 @@ class Imx53_driver : public Gpio::Driver
{ {
if (verbose) PDBG("gpio=%d", gpio); if (verbose) PDBG("gpio=%d", gpio);
Gpio_reg *gpio_reg = _gpio_bank[_gpio_bank_index(gpio)].regs(); Gpio_reg *gpio_reg = _gpio_bank(gpio)->regs();
return gpio_reg->read<Gpio_reg::Pad_stat>(_gpio_index(gpio)); return gpio_reg->read<Gpio_reg::Pad_stat>(_gpio_index(gpio));
} }
@ -174,7 +238,7 @@ class Imx53_driver : public Gpio::Driver
{ {
if (verbose) PDBG("gpio=%d", gpio); if (verbose) PDBG("gpio=%d", gpio);
Gpio_reg *gpio_reg = _gpio_bank[_gpio_bank_index(gpio)].regs(); Gpio_reg *gpio_reg = _gpio_bank(gpio)->regs();
gpio_reg->write<Gpio_reg::Int_conf>(Gpio_reg::Int_conf::FAL_EDGE, gpio_reg->write<Gpio_reg::Int_conf>(Gpio_reg::Int_conf::FAL_EDGE,
_gpio_index(gpio)); _gpio_index(gpio));
} }
@ -183,7 +247,7 @@ class Imx53_driver : public Gpio::Driver
{ {
if (verbose) PDBG("gpio=%d", gpio); if (verbose) PDBG("gpio=%d", gpio);
Gpio_reg *gpio_reg = _gpio_bank[_gpio_bank_index(gpio)].regs(); Gpio_reg *gpio_reg = _gpio_bank(gpio)->regs();
gpio_reg->write<Gpio_reg::Int_conf>(Gpio_reg::Int_conf::RIS_EDGE, gpio_reg->write<Gpio_reg::Int_conf>(Gpio_reg::Int_conf::RIS_EDGE,
_gpio_index(gpio)); _gpio_index(gpio));
} }
@ -192,7 +256,7 @@ class Imx53_driver : public Gpio::Driver
{ {
if (verbose) PDBG("gpio=%d", gpio); if (verbose) PDBG("gpio=%d", gpio);
Gpio_reg *gpio_reg = _gpio_bank[_gpio_bank_index(gpio)].regs(); Gpio_reg *gpio_reg = _gpio_bank(gpio)->regs();
gpio_reg->write<Gpio_reg::Int_conf>(Gpio_reg::Int_conf::HIGH_LEVEL, gpio_reg->write<Gpio_reg::Int_conf>(Gpio_reg::Int_conf::HIGH_LEVEL,
_gpio_index(gpio)); _gpio_index(gpio));
} }
@ -201,7 +265,7 @@ class Imx53_driver : public Gpio::Driver
{ {
if (verbose) PDBG("gpio=%d", gpio); if (verbose) PDBG("gpio=%d", gpio);
Gpio_reg *gpio_reg = _gpio_bank[_gpio_bank_index(gpio)].regs(); Gpio_reg *gpio_reg = _gpio_bank(gpio)->regs();
gpio_reg->write<Gpio_reg::Int_conf>(Gpio_reg::Int_conf::LOW_LEVEL, gpio_reg->write<Gpio_reg::Int_conf>(Gpio_reg::Int_conf::LOW_LEVEL,
_gpio_index(gpio)); _gpio_index(gpio));
} }
@ -210,7 +274,14 @@ class Imx53_driver : public Gpio::Driver
{ {
if (verbose) PDBG("gpio=%d enable=%d", gpio, enable); if (verbose) PDBG("gpio=%d enable=%d", gpio, enable);
_gpio_bank[_gpio_bank_index(gpio)].irq(_gpio_index(gpio), enable); _gpio_bank(gpio)->irq(_gpio_index(gpio), enable);
}
void ack_irq(unsigned gpio)
{
if (verbose) PDBG("gpio=%d ack_irq", gpio);
_gpio_bank(gpio)->ack_irq(_gpio_index(gpio));
} }
void register_signal(unsigned gpio, void register_signal(unsigned gpio,
@ -218,59 +289,24 @@ class Imx53_driver : public Gpio::Driver
{ {
if (verbose) PDBG("gpio=%d", gpio); if (verbose) PDBG("gpio=%d", gpio);
_gpio_bank[_gpio_bank_index(gpio)].sigh(_gpio_index(gpio), cap); } _gpio_bank(gpio)->sigh(_gpio_index(gpio), cap); }
void unregister_signal(unsigned gpio) void unregister_signal(unsigned gpio)
{ {
if (verbose) PDBG("gpio=%d", gpio); if (verbose) PDBG("gpio=%d", gpio);
Genode::Signal_context_capability cap; Genode::Signal_context_capability cap;
_gpio_bank[_gpio_bank_index(gpio)].sigh(_gpio_index(gpio), cap); _gpio_bank(gpio)->sigh(_gpio_index(gpio), cap);
} }
bool gpio_valid(unsigned gpio) { return gpio < (MAX_PINS*MAX_BANKS); } bool gpio_valid(unsigned gpio) { return gpio < (MAX_PINS*MAX_BANKS); }
}; };
Imx53_driver::Gpio_bank Imx53_driver::_gpio_bank[Imx53_driver::MAX_BANKS] = { Imx53_driver &Imx53_driver::factory(Server::Entrypoint &ep)
{ Genode::Board_base::GPIO1_MMIO_BASE, Genode::Board_base::GPIO1_MMIO_SIZE,
Genode::Board_base::GPIO1_IRQL, Genode::Board_base::GPIO1_IRQH },
{ Genode::Board_base::GPIO2_MMIO_BASE, Genode::Board_base::GPIO2_MMIO_SIZE,
Genode::Board_base::GPIO2_IRQL, Genode::Board_base::GPIO2_IRQH },
{ Genode::Board_base::GPIO3_MMIO_BASE, Genode::Board_base::GPIO3_MMIO_SIZE,
Genode::Board_base::GPIO3_IRQL, Genode::Board_base::GPIO3_IRQH },
{ Genode::Board_base::GPIO4_MMIO_BASE, Genode::Board_base::GPIO4_MMIO_SIZE,
Genode::Board_base::GPIO4_IRQL, Genode::Board_base::GPIO4_IRQH },
{ Genode::Board_base::GPIO5_MMIO_BASE, Genode::Board_base::GPIO5_MMIO_SIZE,
Genode::Board_base::GPIO5_IRQL, Genode::Board_base::GPIO5_IRQH },
{ Genode::Board_base::GPIO6_MMIO_BASE, Genode::Board_base::GPIO6_MMIO_SIZE,
Genode::Board_base::GPIO6_IRQL, Genode::Board_base::GPIO6_IRQH },
{ Genode::Board_base::GPIO7_MMIO_BASE, Genode::Board_base::GPIO7_MMIO_SIZE,
Genode::Board_base::GPIO7_IRQL, Genode::Board_base::GPIO7_IRQH }
};
Imx53_driver& Imx53_driver::factory()
{ {
static Imx53_driver driver; static Imx53_driver driver(ep);
return driver; return driver;
} }
void Imx53_driver::Gpio_bank::handle_irq()
{
Genode::Lock::Guard lock_guard(_lock);
unsigned long status = _reg.read<Gpio_reg::Int_stat>();
for(unsigned i = 0; i < MAX_PINS; i++) {
if ((status & (1 << i)) && _irq_enabled[i] &&
_sig_cap[i].valid())
Genode::Signal_transmitter(_sig_cap[i]).submit();
}
_reg.write<Gpio_reg::Int_stat>(0xffffffff);
}
#endif /* _DRIVER_H_ */ #endif /* _DRIVER_H_ */

View File

@ -8,7 +8,7 @@
/* /*
* Copyright (C) 2012 Ksys Labs LLC * Copyright (C) 2012 Ksys Labs LLC
* Copyright (C) 2012-2013 Genode Labs GmbH * Copyright (C) 2012-2015 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
@ -20,35 +20,46 @@
#include <cap_session/connection.h> #include <cap_session/connection.h>
#include <gpio/component.h> #include <gpio/component.h>
#include <gpio/config.h> #include <gpio/config.h>
#include <os/server.h>
/* local includes */ /* local includes */
#include <driver.h> #include <driver.h>
int main(int, char **) struct Main
{ {
using namespace Genode; Server::Entrypoint &ep;
Genode::Sliced_heap sliced_heap;
Imx53_driver &driver;
Gpio::Root root;
printf("--- i.MX53 gpio driver ---\n"); Main(Server::Entrypoint &ep)
:
ep(ep),
sliced_heap(Genode::env()->ram_session(), Genode::env()->rm_session()),
driver(Imx53_driver::factory(ep)),
root(&ep.rpc_ep(), &sliced_heap, driver)
{
using namespace Genode;
Imx53_driver &driver = Imx53_driver::factory(); printf("--- i.MX53 gpio driver ---\n");
Gpio::process_config(driver);
/* Gpio::process_config(driver);
* Initialize server entry point
*/
enum { STACK_SIZE = 4096 };
static Cap_connection cap;
Sliced_heap sliced_heap(env()->ram_session(), env()->rm_session());
static Rpc_entrypoint ep(&cap, STACK_SIZE, "gpio_ep");
static Gpio::Root gpio_root(&ep, &sliced_heap, driver);
/* /*
* Announce service * Announce service
*/ */
env()->parent()->announce(ep.manage(&gpio_root)); env()->parent()->announce(ep.manage(root));
}
};
Genode::sleep_forever();
return 0; /************
** Server **
************/
namespace Server {
char const *name() { return "gpio_drv_ep"; }
size_t stack_size() { return 1024*sizeof(long); }
void construct(Entrypoint &ep) { static Main server(ep); }
} }

View File

@ -1,7 +1,7 @@
TARGET = gpio_drv TARGET = gpio_drv
REQUIRES = imx53 REQUIRES = imx53
SRC_CC = main.cc SRC_CC = main.cc
LIBS = base config LIBS = base config server
INC_DIR += $(PRG_DIR) INC_DIR += $(PRG_DIR)
vpath main.cc $(PRG_DIR) vpath main.cc $(PRG_DIR)

View File

@ -33,6 +33,7 @@ class Omap4_driver : public Gpio::Driver
private: private:
enum { enum {
PIN_SHIFT = 5,
MAX_BANKS = 6, MAX_BANKS = 6,
MAX_PINS = 32 MAX_PINS = 32
}; };
@ -47,44 +48,45 @@ class Omap4_driver : public Gpio::Driver
} _delayer; } _delayer;
class Gpio_bank : public Genode::Thread<4096> class Gpio_bank
{ {
private: private:
Gpio_reg _reg; Gpio_reg _reg;
Genode::Irq_connection _irq; Genode::Irq_connection _irq;
Genode::Signal_context_capability _sig_cap[MAX_PINS]; Genode::Signal_rpc_member<Gpio_bank> _dispatcher;
bool _irq_enabled[MAX_PINS]; Genode::Signal_context_capability _sig_cap[MAX_PINS];
bool _irq_enabled[MAX_PINS];
void _handle(unsigned)
{
_reg.write<Gpio_reg::Irqstatus_0>(0xffffffff);
unsigned long status = _reg.read<Gpio_reg::Irqstatus_0>();
for(unsigned i = 0; i < MAX_PINS; i++) {
if ((status & (1 << i)) && _irq_enabled[i] &&
_sig_cap[i].valid())
Genode::Signal_transmitter(_sig_cap[i]).submit();
}
_irq.ack_irq();
}
public: public:
Gpio_bank(Genode::addr_t base, Genode::size_t size, Gpio_bank(Server::Entrypoint &ep,
Genode::addr_t base, Genode::size_t size,
unsigned irq) unsigned irq)
: Genode::Thread<4096>("irq handler"), : _reg(base, size), _irq(irq),
_reg(base, size), _irq(irq) _dispatcher(ep, *this, &Gpio_bank::_handle)
{ {
for (unsigned i = 0; i < MAX_PINS; i++) for (unsigned i = 0; i < MAX_PINS; i++)
_irq_enabled[i] = false; _irq_enabled[i] = false;
start();
}
void entry() _irq.sigh(_dispatcher);
{ _irq.ack_irq();
unsigned long status;
while (true) {
_reg.write<Gpio_reg::Irqstatus_0>(0xffffffff);
_irq.wait_for_irq();
status = _reg.read<Gpio_reg::Irqstatus_0>();
for(unsigned i = 0; i < MAX_PINS; i++) {
if ((status & (1 << i)) && _irq_enabled[i] &&
_sig_cap[i].valid())
Genode::Signal_transmitter(_sig_cap[i]).submit();
}
}
} }
Gpio_reg* regs() { return &_reg; } Gpio_reg* regs() { return &_reg; }
@ -100,28 +102,71 @@ class Omap4_driver : public Gpio::Driver
_irq_enabled[pin] = enable; _irq_enabled[pin] = enable;
} }
void ack_irq(int pin) { PDBG("not implemented"); }
void sigh(int pin, Genode::Signal_context_capability cap) { void sigh(int pin, Genode::Signal_context_capability cap) {
_sig_cap[pin] = cap; } _sig_cap[pin] = cap; }
}; };
Server::Entrypoint &_ep;
static Gpio_bank _gpio_bank[MAX_BANKS]; Gpio_bank _gpio_bank_0;
Gpio_bank _gpio_bank_1;
Gpio_bank _gpio_bank_2;
Gpio_bank _gpio_bank_3;
Gpio_bank _gpio_bank_4;
Gpio_bank _gpio_bank_5;
Gpio_bank *_gpio_bank(int gpio)
{
switch (gpio >> PIN_SHIFT) {
case 0:
return &_gpio_bank_0;
case 1:
return &_gpio_bank_1;
case 2:
return &_gpio_bank_2;
case 3:
return &_gpio_bank_3;
case 4:
return &_gpio_bank_4;
case 5:
return &_gpio_bank_5;
}
PERR("no Gpio_bank for pin %d available", gpio);
return 0;
}
int _gpio_bank_index(int gpio) { return gpio >> 5; }
int _gpio_index(int gpio) { return gpio & 0x1f; } int _gpio_index(int gpio) { return gpio & 0x1f; }
Omap4_driver() Omap4_driver(Server::Entrypoint &ep)
:
_ep(ep),
_gpio_bank_0(_ep, Genode::Board_base::GPIO1_MMIO_BASE, Genode::Board_base::GPIO1_MMIO_SIZE,
Genode::Board_base::GPIO1_IRQ),
_gpio_bank_1(_ep, Genode::Board_base::GPIO2_MMIO_BASE, Genode::Board_base::GPIO2_MMIO_SIZE,
Genode::Board_base::GPIO2_IRQ),
_gpio_bank_2(_ep, Genode::Board_base::GPIO3_MMIO_BASE, Genode::Board_base::GPIO3_MMIO_SIZE,
Genode::Board_base::GPIO3_IRQ),
_gpio_bank_3(_ep, Genode::Board_base::GPIO4_MMIO_BASE, Genode::Board_base::GPIO4_MMIO_SIZE,
Genode::Board_base::GPIO4_IRQ),
_gpio_bank_4(_ep, Genode::Board_base::GPIO5_MMIO_BASE, Genode::Board_base::GPIO5_MMIO_SIZE,
Genode::Board_base::GPIO5_IRQ),
_gpio_bank_5(_ep, Genode::Board_base::GPIO6_MMIO_BASE, Genode::Board_base::GPIO6_MMIO_SIZE,
Genode::Board_base::GPIO6_IRQ)
{ {
for (int i = 0; i < MAX_BANKS; ++i) { for (int i = 0; i < MAX_BANKS; ++i) {
if (verbose) if (verbose)
PDBG("GPIO%d ctrl=%08x", PDBG("GPIO%d ctrl=%08x",
i+1, _gpio_bank[i].regs()->read<Gpio_reg::Ctrl>()); i+1, _gpio_bank(i << PIN_SHIFT)->regs()->read<Gpio_reg::Ctrl>());
} }
} }
public: public:
static Omap4_driver& factory(); static Omap4_driver& factory(Server::Entrypoint &ep);
/****************************** /******************************
@ -132,7 +177,7 @@ class Omap4_driver : public Gpio::Driver
{ {
if (verbose) PDBG("gpio=%d input=%d", gpio, input); if (verbose) PDBG("gpio=%d input=%d", gpio, input);
Gpio_reg *gpio_reg = _gpio_bank[_gpio_bank_index(gpio)].regs(); Gpio_reg *gpio_reg = _gpio_bank(gpio)->regs();
gpio_reg->write<Gpio_reg::Oe>(input ? 1 : 0, _gpio_index(gpio)); gpio_reg->write<Gpio_reg::Oe>(input ? 1 : 0, _gpio_index(gpio));
} }
@ -140,7 +185,7 @@ class Omap4_driver : public Gpio::Driver
{ {
if (verbose) PDBG("gpio=%d level=%d", gpio, level); if (verbose) PDBG("gpio=%d level=%d", gpio, level);
Gpio_reg *gpio_reg = _gpio_bank[_gpio_bank_index(gpio)].regs(); Gpio_reg *gpio_reg = _gpio_bank(gpio)->regs();
if (level) if (level)
gpio_reg->write<Gpio_reg::Setdataout>(1 << _gpio_index(gpio)); gpio_reg->write<Gpio_reg::Setdataout>(1 << _gpio_index(gpio));
@ -152,7 +197,7 @@ class Omap4_driver : public Gpio::Driver
{ {
if (verbose) PDBG("gpio=%d", gpio); if (verbose) PDBG("gpio=%d", gpio);
Gpio_reg *gpio_reg = _gpio_bank[_gpio_bank_index(gpio)].regs(); Gpio_reg *gpio_reg = _gpio_bank(gpio)->regs();
return gpio_reg->read<Gpio_reg::Datain>(_gpio_index(gpio)); return gpio_reg->read<Gpio_reg::Datain>(_gpio_index(gpio));
} }
@ -160,7 +205,7 @@ class Omap4_driver : public Gpio::Driver
{ {
if (verbose) PDBG("gpio=%d enable=%d", gpio, enable); if (verbose) PDBG("gpio=%d enable=%d", gpio, enable);
Gpio_reg *gpio_reg = _gpio_bank[_gpio_bank_index(gpio)].regs(); Gpio_reg *gpio_reg = _gpio_bank(gpio)->regs();
gpio_reg->write<Gpio_reg::Debounceenable>(enable ? 1 : 0, gpio_reg->write<Gpio_reg::Debounceenable>(enable ? 1 : 0,
_gpio_index(gpio)); _gpio_index(gpio));
} }
@ -178,7 +223,7 @@ class Omap4_driver : public Gpio::Driver
else else
debounce = (us / 0x1f) - 1; debounce = (us / 0x1f) - 1;
Gpio_reg *gpio_reg = _gpio_bank[_gpio_bank_index(gpio)].regs(); Gpio_reg *gpio_reg = _gpio_bank(gpio)->regs();
gpio_reg->write<Gpio_reg::Debouncingtime::Time>(debounce); gpio_reg->write<Gpio_reg::Debouncingtime::Time>(debounce);
} }
@ -186,7 +231,7 @@ class Omap4_driver : public Gpio::Driver
{ {
if (verbose) PDBG("gpio=%d", gpio); if (verbose) PDBG("gpio=%d", gpio);
Gpio_reg *gpio_reg = _gpio_bank[_gpio_bank_index(gpio)].regs(); Gpio_reg *gpio_reg = _gpio_bank(gpio)->regs();
gpio_reg->write<Gpio_reg::Leveldetect0> (0, _gpio_index(gpio)); gpio_reg->write<Gpio_reg::Leveldetect0> (0, _gpio_index(gpio));
gpio_reg->write<Gpio_reg::Leveldetect1> (0, _gpio_index(gpio)); gpio_reg->write<Gpio_reg::Leveldetect1> (0, _gpio_index(gpio));
gpio_reg->write<Gpio_reg::Fallingdetect>(1, _gpio_index(gpio)); gpio_reg->write<Gpio_reg::Fallingdetect>(1, _gpio_index(gpio));
@ -197,7 +242,7 @@ class Omap4_driver : public Gpio::Driver
{ {
if (verbose) PDBG("gpio=%d", gpio); if (verbose) PDBG("gpio=%d", gpio);
Gpio_reg *gpio_reg = _gpio_bank[_gpio_bank_index(gpio)].regs(); Gpio_reg *gpio_reg = _gpio_bank(gpio)->regs();
gpio_reg->write<Gpio_reg::Leveldetect0> (0, _gpio_index(gpio)); gpio_reg->write<Gpio_reg::Leveldetect0> (0, _gpio_index(gpio));
gpio_reg->write<Gpio_reg::Leveldetect1> (0, _gpio_index(gpio)); gpio_reg->write<Gpio_reg::Leveldetect1> (0, _gpio_index(gpio));
gpio_reg->write<Gpio_reg::Fallingdetect>(0, _gpio_index(gpio)); gpio_reg->write<Gpio_reg::Fallingdetect>(0, _gpio_index(gpio));
@ -208,7 +253,7 @@ class Omap4_driver : public Gpio::Driver
{ {
if (verbose) PDBG("gpio=%d", gpio); if (verbose) PDBG("gpio=%d", gpio);
Gpio_reg *gpio_reg = _gpio_bank[_gpio_bank_index(gpio)].regs(); Gpio_reg *gpio_reg = _gpio_bank(gpio)->regs();
gpio_reg->write<Gpio_reg::Leveldetect0> (0, _gpio_index(gpio)); gpio_reg->write<Gpio_reg::Leveldetect0> (0, _gpio_index(gpio));
gpio_reg->write<Gpio_reg::Leveldetect1> (1, _gpio_index(gpio)); gpio_reg->write<Gpio_reg::Leveldetect1> (1, _gpio_index(gpio));
gpio_reg->write<Gpio_reg::Fallingdetect>(0, _gpio_index(gpio)); gpio_reg->write<Gpio_reg::Fallingdetect>(0, _gpio_index(gpio));
@ -219,7 +264,7 @@ class Omap4_driver : public Gpio::Driver
{ {
if (verbose) PDBG("gpio=%d", gpio); if (verbose) PDBG("gpio=%d", gpio);
Gpio_reg *gpio_reg = _gpio_bank[_gpio_bank_index(gpio)].regs(); Gpio_reg *gpio_reg = _gpio_bank(gpio)->regs();
gpio_reg->write<Gpio_reg::Leveldetect0> (1, _gpio_index(gpio)); gpio_reg->write<Gpio_reg::Leveldetect0> (1, _gpio_index(gpio));
gpio_reg->write<Gpio_reg::Leveldetect1> (0, _gpio_index(gpio)); gpio_reg->write<Gpio_reg::Leveldetect1> (0, _gpio_index(gpio));
gpio_reg->write<Gpio_reg::Fallingdetect>(0, _gpio_index(gpio)); gpio_reg->write<Gpio_reg::Fallingdetect>(0, _gpio_index(gpio));
@ -230,7 +275,14 @@ class Omap4_driver : public Gpio::Driver
{ {
if (verbose) PDBG("gpio=%d enable=%d", gpio, enable); if (verbose) PDBG("gpio=%d enable=%d", gpio, enable);
_gpio_bank[_gpio_bank_index(gpio)].irq(_gpio_index(gpio), enable); _gpio_bank(gpio)->irq(_gpio_index(gpio), enable);
}
void ack_irq(unsigned gpio)
{
if (verbose) PDBG("gpio=%d", gpio);
_gpio_bank(gpio)->ack_irq(_gpio_index(gpio));
} }
void register_signal(unsigned gpio, void register_signal(unsigned gpio,
@ -238,39 +290,23 @@ class Omap4_driver : public Gpio::Driver
{ {
if (verbose) PDBG("gpio=%d", gpio); if (verbose) PDBG("gpio=%d", gpio);
_gpio_bank[_gpio_bank_index(gpio)].sigh(_gpio_index(gpio), cap); } _gpio_bank(gpio)->sigh(_gpio_index(gpio), cap); }
void unregister_signal(unsigned gpio) void unregister_signal(unsigned gpio)
{ {
if (verbose) PDBG("gpio=%d", gpio); if (verbose) PDBG("gpio=%d", gpio);
Genode::Signal_context_capability cap; Genode::Signal_context_capability cap;
_gpio_bank[_gpio_bank_index(gpio)].sigh(_gpio_index(gpio), cap); _gpio_bank(gpio)->sigh(_gpio_index(gpio), cap);
} }
bool gpio_valid(unsigned gpio) { return gpio < (MAX_PINS*MAX_BANKS); } bool gpio_valid(unsigned gpio) { return gpio < (MAX_PINS*MAX_BANKS); }
}; };
Omap4_driver::Gpio_bank Omap4_driver::_gpio_bank[Omap4_driver::MAX_BANKS] = { Omap4_driver& Omap4_driver::factory(Server::Entrypoint &ep)
{ Genode::Board_base::GPIO1_MMIO_BASE, Genode::Board_base::GPIO1_MMIO_SIZE,
Genode::Board_base::GPIO1_IRQ },
{ Genode::Board_base::GPIO2_MMIO_BASE, Genode::Board_base::GPIO2_MMIO_SIZE,
Genode::Board_base::GPIO2_IRQ },
{ Genode::Board_base::GPIO3_MMIO_BASE, Genode::Board_base::GPIO3_MMIO_SIZE,
Genode::Board_base::GPIO3_IRQ },
{ Genode::Board_base::GPIO4_MMIO_BASE, Genode::Board_base::GPIO4_MMIO_SIZE,
Genode::Board_base::GPIO4_IRQ },
{ Genode::Board_base::GPIO5_MMIO_BASE, Genode::Board_base::GPIO5_MMIO_SIZE,
Genode::Board_base::GPIO5_IRQ },
{ Genode::Board_base::GPIO6_MMIO_BASE, Genode::Board_base::GPIO6_MMIO_SIZE,
Genode::Board_base::GPIO6_IRQ },
};
Omap4_driver& Omap4_driver::factory()
{ {
static Omap4_driver driver; static Omap4_driver driver(ep);
return driver; return driver;
} }

View File

@ -7,7 +7,7 @@
/* /*
* Copyright (C) 2012 Ksys Labs LLC * Copyright (C) 2012 Ksys Labs LLC
* Copyright (C) 2012-2013 Genode Labs GmbH * Copyright (C) 2012-2015 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
@ -19,35 +19,45 @@
#include <cap_session/connection.h> #include <cap_session/connection.h>
#include <gpio/component.h> #include <gpio/component.h>
#include <gpio/config.h> #include <gpio/config.h>
#include <os/server.h>
/* local includes */ /* local includes */
#include <driver.h> #include <driver.h>
int main(int, char **) struct Main
{ {
using namespace Genode; Server::Entrypoint &ep;
Genode::Sliced_heap sliced_heap;
Omap4_driver &driver;
Gpio::Root root;
printf("--- omap4 gpio driver ---\n"); Main(Server::Entrypoint &ep)
:
ep(ep),
sliced_heap(Genode::env()->ram_session(), Genode::env()->rm_session()),
driver(Omap4_driver::factory(ep)),
root(&ep.rpc_ep(), &sliced_heap, driver)
{
using namespace Genode;
Omap4_driver &driver = Omap4_driver::factory(); printf("--- omap4 gpio driver ---\n");
Gpio::process_config(driver);
/* Gpio::process_config(driver);
* Initialize server entry point
*/
enum { STACK_SIZE = 4096 };
static Cap_connection cap;
Sliced_heap sliced_heap(env()->ram_session(), env()->rm_session());
static Rpc_entrypoint ep(&cap, STACK_SIZE, "gpio_ep");
static Gpio::Root gpio_root(&ep, &sliced_heap, driver);
/* /*
* Announce service * Announce service
*/ */
env()->parent()->announce(ep.manage(&gpio_root)); env()->parent()->announce(ep.manage(root));
}
};
Genode::sleep_forever(); /************
return 0; ** Server **
************/
namespace Server {
char const *name() { return "gpio_drv_ep"; }
size_t stack_size() { return 1024*sizeof(long); }
void construct(Entrypoint &ep) { static Main server(ep); }
} }

View File

@ -1,7 +1,7 @@
TARGET = gpio_drv TARGET = gpio_drv
REQUIRES = omap4 REQUIRES = omap4
SRC_CC = main.cc SRC_CC = main.cc
LIBS = base config LIBS = base config server
INC_DIR += $(PRG_DIR) INC_DIR += $(PRG_DIR)
vpath main.cc $(PRG_DIR) vpath main.cc $(PRG_DIR)

View File

@ -6,7 +6,7 @@
*/ */
/* /*
* Copyright (C) 2006-2013 Genode Labs GmbH * Copyright (C) 2006-2015 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
@ -22,6 +22,7 @@
#include <input_session/input_session.h> #include <input_session/input_session.h>
#include <input/event.h> #include <input/event.h>
#include <base/printf.h> #include <base/printf.h>
#include <os/server.h>
using namespace Genode; using namespace Genode;
@ -71,28 +72,33 @@ namespace Input {
} }
int main(int argc, char **argv) struct Main
{ {
/* create dataspace for event buffer that is shared with the client */ Server::Entrypoint &ep;
try { ev_ds_cap = env()->ram_session()->alloc(MAX_EVENTS*sizeof(Input::Event)); } Input::Root root;
catch (Ram_session::Alloc_failed) {
PERR("Could not allocate dataspace for event buffer"); Main(Server::Entrypoint &ep)
return 1; : ep(ep), root(&ep.rpc_ep(), Genode::env()->heap())
{
/* create dataspace for event buffer that is shared with the client */
try { ev_ds_cap = env()->ram_session()->alloc(MAX_EVENTS*sizeof(Input::Event)); }
catch (Ram_session::Alloc_failed) {
PERR("Could not allocate dataspace for event buffer");
throw Genode::Exception();
}
/* tell parent about the service */
env()->parent()->announce(ep.manage(root));
} }
};
/* initialize server entry point */
enum { STACK_SIZE = 4096 };
static Cap_connection cap;
static Rpc_entrypoint ep(&cap, STACK_SIZE, "input_ep");
/* entry point serving input root interface */ /************
static Input::Root input_root(&ep, env()->heap()); ** Server **
************/
/* tell parent about the service */ namespace Server {
env()->parent()->announce(ep.manage(&input_root)); char const *name() { return "input_drv_ep"; }
size_t stack_size() { return 1024*sizeof(long); }
/* main's done - go to sleep */ void construct(Entrypoint &ep) { static Main server(ep); }
sleep_forever();
return 0;
} }

View File

@ -1,3 +1,3 @@
TARGET = dummy_input_drv TARGET = dummy_input_drv
SRC_CC = main.cc SRC_CC = main.cc
LIBS = base LIBS = base server

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (C) 2013 Genode Labs GmbH * Copyright (C) 2013-2015 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
@ -16,7 +16,6 @@
/* Genode includes */ /* Genode includes */
#include <base/env.h> #include <base/env.h>
#include <base/thread.h>
#include <base/signal.h> #include <base/signal.h>
#include <gpio_session/connection.h> #include <gpio_session/connection.h>
@ -29,7 +28,7 @@ namespace Input {
} }
class Input::Tablet_driver : Genode::Thread<8192> class Input::Tablet_driver
{ {
private: private:
@ -38,69 +37,66 @@ class Input::Tablet_driver : Genode::Thread<8192>
GPIO_BUTTON = 132, GPIO_BUTTON = 132,
}; };
Event_queue &_ev_queue; Event_queue &_ev_queue;
Gpio::Connection _gpio_ts; Gpio::Connection _gpio_ts;
Gpio::Connection _gpio_bt; Gpio::Connection _gpio_bt;
Genode::Signal_receiver _receiver; Genode::Irq_session_client _irq_ts;
Genode::Signal_context _ts_rx; Genode::Irq_session_client _irq_bt;
Genode::Signal_context _bt_rx; Genode::Signal_rpc_member<Tablet_driver> _ts_dispatcher;
Genode::Signal_context_capability _ts_sig_cap; Genode::Signal_rpc_member<Tablet_driver> _bt_dispatcher;
Genode::Signal_context_capability _bt_sig_cap; Touchscreen _touchscreen;
Touchscreen _touchscreen; Buttons _buttons;
Buttons _buttons;
Genode::Signal_context_capability _init_ts_gpio() void _handle_ts(unsigned)
{ {
Genode::Signal_context_capability ret = _receiver.manage(&_ts_rx); _touchscreen.event(_ev_queue);
_irq_ts.ack_irq();
}
void _handle_bt(unsigned)
{
_buttons.event(_ev_queue);
_irq_bt.ack_irq();
}
Tablet_driver(Server::Entrypoint &ep, Event_queue &ev_queue)
:
_ev_queue(ev_queue),
_gpio_ts(GPIO_TOUCH),
_gpio_bt(GPIO_BUTTON),
_irq_ts(_gpio_ts.irq_session(Gpio::Session::LOW_LEVEL)),
_irq_bt(_gpio_bt.irq_session(Gpio::Session::FALLING_EDGE)),
_ts_dispatcher(ep, *this, &Tablet_driver::_handle_ts),
_bt_dispatcher(ep, *this, &Tablet_driver::_handle_bt),
_touchscreen(ep), _buttons(ep)
{
/* GPIO touchscreen handling */
_gpio_ts.direction(Gpio::Session::OUT); _gpio_ts.direction(Gpio::Session::OUT);
_gpio_ts.write(true); _gpio_ts.write(true);
_gpio_ts.direction(Gpio::Session::IN); _gpio_ts.direction(Gpio::Session::IN);
_gpio_ts.irq_sigh(_ts_sig_cap);
_gpio_ts.irq_type(Gpio::Session::LOW_LEVEL);
_gpio_ts.irq_enable(true);
return ret;
}
Genode::Signal_context_capability _init_bt_gpio() _irq_ts.sigh(_ts_dispatcher);
{ _irq_ts.ack_irq();
Genode::Signal_context_capability ret = _receiver.manage(&_bt_rx);
/* GPIO button handling */
_gpio_bt.direction(Gpio::Session::OUT); _gpio_bt.direction(Gpio::Session::OUT);
_gpio_bt.write(true); _gpio_bt.write(true);
_gpio_bt.direction(Gpio::Session::IN); _gpio_bt.direction(Gpio::Session::IN);
_gpio_bt.irq_sigh(_bt_sig_cap);
_gpio_bt.irq_type(Gpio::Session::FALLING_EDGE);
_gpio_bt.irq_enable(true);
return ret;
}
Tablet_driver(Event_queue &ev_queue) _irq_bt.sigh(_bt_dispatcher);
: Thread("touchscreen_signal_handler"), _irq_bt.ack_irq();
_ev_queue(ev_queue), }
_gpio_ts(GPIO_TOUCH),
_gpio_bt(GPIO_BUTTON),
_ts_sig_cap(_init_ts_gpio()),
_bt_sig_cap(_init_bt_gpio()) { start(); }
public: public:
static Tablet_driver* factory(Event_queue &ev_queue); static Tablet_driver* factory(Server::Entrypoint &ep, Event_queue &ev_queue);
void entry()
{
while (true) {
Genode::Signal sig = _receiver.wait_for_signal();
if (sig.context() == &_ts_rx)
_touchscreen.event(_ev_queue);
else if (sig.context() == &_bt_rx)
_buttons.event(_ev_queue);
}
}
}; };
Input::Tablet_driver* Input::Tablet_driver::factory(Event_queue &ev_queue) Input::Tablet_driver* Input::Tablet_driver::factory(Server::Entrypoint &ep,
Event_queue &ev_queue)
{ {
static Input::Tablet_driver driver(ev_queue); static Input::Tablet_driver driver(ep, ev_queue);
return &driver; return &driver;
} }

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (C) 2013 Genode Labs GmbH * Copyright (C) 2013-2015 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
@ -36,6 +36,7 @@ class Input::Touchscreen {
enum I2c_addresses { I2C_ADDR = 0x4 }; enum I2c_addresses { I2C_ADDR = 0x4 };
enum Finger_state { PRESSED, RELEASED }; enum Finger_state { PRESSED, RELEASED };
Irq_handler _irq_handler;
Genode::Attached_io_mem_dataspace _i2c_ds; Genode::Attached_io_mem_dataspace _i2c_ds;
I2c::I2c _i2c; I2c::I2c _i2c;
Genode::uint8_t _buf[10]; Genode::uint8_t _buf[10];
@ -43,11 +44,14 @@ class Input::Touchscreen {
public: public:
Touchscreen() : _i2c_ds(Genode::Board_base::I2C_3_BASE, Touchscreen(Server::Entrypoint &ep)
Genode::Board_base::I2C_3_SIZE), :
_i2c((Genode::addr_t)_i2c_ds.local_addr<void>(), _irq_handler(ep, Genode::Board_base::I2C_3_IRQ),
Genode::Board_base::I2C_3_IRQ), _i2c_ds(Genode::Board_base::I2C_3_BASE,
_state(RELEASED) Genode::Board_base::I2C_3_SIZE),
_i2c((Genode::addr_t)_i2c_ds.local_addr<void>(),
_irq_handler),
_state(RELEASED)
{ {
/* ask for touchscreen firmware version */ /* ask for touchscreen firmware version */
Genode::uint8_t cmd[10] = { 0x03, 0x03, 0xa, 0x01, 0x41 }; Genode::uint8_t cmd[10] = { 0x03, 0x03, 0xa, 0x01, 0x41 };

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (C) 2013 Genode Labs GmbH * Copyright (C) 2013-2015 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
@ -17,7 +17,9 @@
/* Genode includes */ /* Genode includes */
#include <util/mmio.h> #include <util/mmio.h>
#include <timer_session/connection.h> #include <timer_session/connection.h>
#include <irq_session/connection.h>
/* local includes */
#include "irq_handler.h"
namespace I2c namespace I2c
{ {
@ -61,11 +63,10 @@ class I2c::I2c : Genode::Mmio
class No_ack : Genode::Exception {}; class No_ack : Genode::Exception {};
class No_irq : Genode::Exception {};
Timer::Connection _timer; Timer::Connection _timer;
Genode::Irq_connection _irq; Irq_handler &_irq_handler;
void _busy() { while (!read<Status::Busy>()); } void _busy() { while (!read<Status::Busy>()); }
@ -101,15 +102,19 @@ class I2c::I2c : Genode::Mmio
{ {
write<Data>(value); write<Data>(value);
_irq.wait_for_irq(); do { _irq_handler.wait(); }
if (!read<Status::Irq>()) throw No_irq(); while (!read<Status::Irq>());
write<Status::Irq>(0); write<Status::Irq>(0);
if (read<Status::Rcv_ack>()) throw No_ack(); if (read<Status::Rcv_ack>()) throw No_ack();
_irq_handler.ack();
} }
public: public:
I2c(Genode::addr_t const base, unsigned irq) : Mmio(base), _irq(irq) I2c(Genode::addr_t const base, Irq_handler &irq_handler)
: Mmio(base), _irq_handler(irq_handler)
{ {
write<Control>(0); write<Control>(0);
write<Status>(0); write<Status>(0);
@ -128,9 +133,7 @@ class I2c::I2c : Genode::Mmio
_stop(); _stop();
return; return;
} catch(No_ack) { } catch(No_ack) { }
} catch(No_irq) {
}
_stop(); _stop();
} }
} }
@ -150,8 +153,9 @@ class I2c::I2c : Genode::Mmio
for (Genode::size_t i = 0; i < num; i++) { for (Genode::size_t i = 0; i < num; i++) {
_irq.wait_for_irq(); do { _irq_handler.wait(); }
if (!read<Status::Irq>()) throw No_irq(); while (!read<Status::Irq>());
write<Status::Irq>(0); write<Status::Irq>(0);
if (i == num-1) { if (i == num-1) {
@ -167,8 +171,7 @@ class I2c::I2c : Genode::Mmio
_stop(); _stop();
return; return;
} catch(No_irq) { } catch(No_ack) { }
}
_stop(); _stop();
} }
} }

View File

@ -0,0 +1,48 @@
/*
* \brief Input-interrupt handler
* \author Josef Soentgen
* \date 2015-04-08
*/
/*
* Copyright (C) 2015 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _IRQ_HANDLER_H_
#define _IRQ_HANDLER_H_
/* Genode includes */
#include <irq_session/connection.h>
#include <os/server.h>
class Irq_handler
{
private:
Genode::Irq_connection _irq;
Genode::Signal_receiver _sig_rec;
Genode::Signal_dispatcher<Irq_handler> _dispatcher;
void _handle(unsigned) { }
public:
Irq_handler(Server::Entrypoint &ep, int irq_number)
:
_irq(irq_number),
_dispatcher(_sig_rec, *this, &Irq_handler::_handle)
{
_irq.sigh(_dispatcher);
_irq.ack_irq();
}
void wait() { _sig_rec.wait_for_signal(); }
void ack() { _irq.ack_irq(); }
};
#endif /* _IRQ_HANDLER_H_ */

View File

@ -7,7 +7,7 @@
*/ */
/* /*
* Copyright (C) 2006-2013 Genode Labs GmbH * Copyright (C) 2006-2015 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
@ -22,40 +22,47 @@
#include <input/component.h> #include <input/component.h>
#include <input/root.h> #include <input/root.h>
#include <base/printf.h> #include <base/printf.h>
#include <os/server.h>
/* local includes */ /* local includes */
#include <driver.h> #include <driver.h>
using namespace Genode; using namespace Genode;
int main(int argc, char **argv)
struct Main
{ {
/* initialize server entry point */ Server::Entrypoint &ep;
enum { STACK_SIZE = 4096 };
static Cap_connection cap;
static Rpc_entrypoint ep(&cap, STACK_SIZE, "input_ep");
static Input::Session_component session; Input::Session_component session;
Input::Root_component root;
Platform::Connection plat_drv; Main(Server::Entrypoint &ep)
switch (plat_drv.revision()) { : ep(ep), root(ep.rpc_ep(), session)
case Platform::Session::SMD: {
plat_drv.enable(Platform::Session::I2C_2); Platform::Connection plat_drv;
plat_drv.enable(Platform::Session::I2C_3); switch (plat_drv.revision()) {
plat_drv.enable(Platform::Session::BUTTONS); case Platform::Session::SMD:
Input::Tablet_driver::factory(session.event_queue()); plat_drv.enable(Platform::Session::I2C_2);
break; plat_drv.enable(Platform::Session::I2C_3);
default: plat_drv.enable(Platform::Session::BUTTONS);
PWRN("No input driver available for this board"); Input::Tablet_driver::factory(ep, session.event_queue());
break;
default:
PWRN("No input driver available for this board");
}
/* tell parent about the service */
env()->parent()->announce(ep.manage(root));
} }
};
/* entry point serving input root interface */ /************
static Input::Root_component root(ep, session); ** Server **
************/
/* tell parent about the service */ namespace Server {
env()->parent()->announce(ep.manage(&root)); char const *name() { return "input_drv_ep"; }
size_t stack_size() { return 2*1024*sizeof(long); }
/* main's done - go to sleep */ void construct(Entrypoint &ep) { static Main server(ep); }
sleep_forever();
return 0;
} }

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (C) 2013 Genode Labs GmbH * Copyright (C) 2013-2015 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
@ -45,16 +45,19 @@ class Input::Buttons {
POWER = 8, POWER = 8,
}; };
Irq_handler _irq_handler;
Genode::Attached_io_mem_dataspace _i2c_ds; Genode::Attached_io_mem_dataspace _i2c_ds;
I2c::I2c _i2c; I2c::I2c _i2c;
Genode::uint8_t _state; Genode::uint8_t _state;
public: public:
Buttons() : _i2c_ds(Genode::Board_base::I2C_2_BASE, Buttons(Server::Entrypoint &ep) :
_irq_handler(ep, Genode::Board_base::I2C_2_IRQ),
_i2c_ds(Genode::Board_base::I2C_2_BASE,
Genode::Board_base::I2C_2_SIZE), Genode::Board_base::I2C_2_SIZE),
_i2c((Genode::addr_t)_i2c_ds.local_addr<void>(), _i2c((Genode::addr_t)_i2c_ds.local_addr<void>(),
Genode::Board_base::I2C_2_IRQ), _irq_handler),
_state(0) _state(0)
{ {
static Genode::uint8_t init_cmd[][2] = { static Genode::uint8_t init_cmd[][2] = {

View File

@ -1,5 +1,5 @@
TARGET = input_drv TARGET = input_drv
REQUIRES = imx53 REQUIRES = imx53
SRC_CC = main.cc SRC_CC = main.cc
LIBS = base LIBS = base server
INC_DIR += $(PRG_DIR) INC_DIR += $(PRG_DIR)

View File

@ -14,37 +14,43 @@
#ifndef _IRQ_HANDLER_H_ #ifndef _IRQ_HANDLER_H_
#define _IRQ_HANDLER_H_ #define _IRQ_HANDLER_H_
/* Genode includes */
#include <base/thread.h> #include <base/thread.h>
#include <irq_session/connection.h> #include <irq_session/connection.h>
#include <os/server.h>
/* local includes */
#include "input_driver.h" #include "input_driver.h"
class Irq_handler : Genode::Thread<4096> class Irq_handler
{ {
private: private:
Genode::Irq_connection _irq; Genode::Irq_connection _irq;
Input_driver &_input_driver; Genode::Signal_rpc_member<Irq_handler> _dispatcher;
Input_driver &_input_driver;
void _handle(unsigned)
{
_irq.ack_irq();
while (_input_driver.event_pending())
_input_driver.handle_event();
}
public: public:
Irq_handler(int irq_number, Input_driver &input_driver) Irq_handler(Server::Entrypoint &ep,
int irq_number, Input_driver &input_driver)
: :
Thread("irq_handler"),
_irq(irq_number), _irq(irq_number),
_dispatcher(ep, *this, &Irq_handler::_handle),
_input_driver(input_driver) _input_driver(input_driver)
{ {
start(); _irq.sigh(_dispatcher);
_irq.ack_irq();
} }
void entry()
{
while (1) {
_irq.wait_for_irq();
while (_input_driver.event_pending())
_input_driver.handle_event();
}
}
}; };
#endif /* _IRQ_HANDLER_H_ */ #endif /* _IRQ_HANDLER_H_ */

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (C) 2007-2013 Genode Labs GmbH * Copyright (C) 2007-2015 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
@ -15,52 +15,52 @@
#define _IRQ_HANDLER_H_ #define _IRQ_HANDLER_H_
/* Genode includes */ /* Genode includes */
#include <base/thread.h>
#include <irq_session/connection.h> #include <irq_session/connection.h>
#include <os/server.h>
/* local includes */ /* local includes */
#include "input_driver.h" #include "input_driver.h"
#include "serial_interface.h" #include "serial_interface.h"
class Irq_handler : Genode::Thread<4096> class Irq_handler
{ {
private: private:
Genode::Irq_connection _irq; Genode::Irq_connection _irq;
Serial_interface *_channel; Genode::Signal_rpc_member<Irq_handler> _dispatcher;
Input_driver &_input_driver; Serial_interface *_channel;
Input_driver &_input_driver;
void _handle(unsigned)
{
_irq.ack_irq();
#ifdef __CODEZERO__
/*
* (Re-)enable device interrupt because Codezero tends to
* disable it in its IRQ handler.
*/
_channel->enable_irq();
#endif
/* check for pending PS/2 input */
while (_input_driver.event_pending())
_input_driver.handle_event();
}
public: public:
Irq_handler(int irq_number, Serial_interface *channel, Input_driver &input_driver) Irq_handler(Server::Entrypoint &ep,
int irq_number, Serial_interface *channel,
Input_driver &input_driver)
: :
Thread("irq_handler"),
_irq(irq_number), _irq(irq_number),
_dispatcher(ep, *this, &Irq_handler::_handle),
_channel(channel), _channel(channel),
_input_driver(input_driver) _input_driver(input_driver)
{ {
start(); _irq.sigh(_dispatcher);
} _irq.ack_irq();
void entry()
{
while (1) {
#ifdef __CODEZERO__
/*
* (Re-)enable device interrupt because Codezero tends to
* disable it in its IRQ handler.
*/
_channel->enable_irq();
#endif
/* check for pending PS/2 input */
while (_input_driver.event_pending())
_input_driver.handle_event();
/* block for new PS/2 data */
_irq.wait_for_irq();
}
} }
}; };

View File

@ -18,6 +18,7 @@
#include <input/component.h> #include <input/component.h>
#include <input/root.h> #include <input/root.h>
#include <cap_session/connection.h> #include <cap_session/connection.h>
#include <os/server.h>
/* local includes */ /* local includes */
#include "ps2_keyboard.h" #include "ps2_keyboard.h"
@ -28,34 +29,38 @@
using namespace Genode; using namespace Genode;
int main(int argc, char **argv) struct Main
{ {
Pl050 pl050; Server::Entrypoint &ep;
Serial_interface *kbd = pl050.kbd_interface(); Pl050 pl050;
Serial_interface *aux = pl050.aux_interface(); Input::Session_component session;
Input::Root_component root;
/* Ps2_mouse ps2_mouse;
* Initialize server entry point Ps2_keyboard ps2_keybd;
*/
enum { STACK_SIZE = 4096 };
static Cap_connection cap;
static Rpc_entrypoint ep(&cap, STACK_SIZE, "ps2_ep");
static Input::Session_component session; Irq_handler ps2_mouse_irq;
static Input::Root_component root(ep, session); Irq_handler ps2_keybd_irq;
Ps2_mouse ps2_mouse(*aux, session.event_queue()); Main(Server::Entrypoint &ep)
Ps2_keyboard ps2_keybd(*kbd, session.event_queue(), true); : ep(ep), root(ep.rpc_ep(), session),
ps2_mouse(*pl050.aux_interface(), session.event_queue()),
ps2_keybd(*pl050.kbd_interface(), session.event_queue(), true),
ps2_mouse_irq(ep, PL050_MOUSE_IRQ, pl050.aux_interface(), ps2_mouse),
ps2_keybd_irq(ep, PL050_KEYBD_IRQ, pl050.kbd_interface(), ps2_keybd)
{
env()->parent()->announce(ep.manage(root));
}
};
Irq_handler ps2_mouse_irq(PL050_MOUSE_IRQ, aux, ps2_mouse);
Irq_handler ps2_keybd_irq(PL050_KEYBD_IRQ, kbd, ps2_keybd);
/* /************
* Let the entry point serve the input root interface ** Server **
*/ ************/
env()->parent()->announce(ep.manage(&root));
Genode::sleep_forever(); namespace Server {
return 0; char const *name() { return "ps2_drv_ep"; }
size_t stack_size() { return 1024*sizeof(long); }
void construct(Entrypoint &ep) { static Main server(ep); }
} }

View File

@ -1,6 +1,6 @@
TARGET = ps2_drv TARGET = ps2_drv
REQUIRES = pl050 REQUIRES = pl050
SRC_CC = main.cc SRC_CC = main.cc
LIBS = base LIBS = base server
INC_DIR += $(PRG_DIR) $(PRG_DIR)/.. INC_DIR += $(PRG_DIR) $(PRG_DIR)/..

View File

@ -11,13 +11,16 @@
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
*/ */
/* Genode includes */
#include <base/env.h> #include <base/env.h>
#include <base/printf.h> #include <base/printf.h>
#include <base/sleep.h> #include <base/sleep.h>
#include <input/component.h> #include <input/component.h>
#include <input/root.h> #include <input/root.h>
#include <cap_session/connection.h> #include <cap_session/connection.h>
#include <os/server.h>
/* local includes */
#include "i8042.h" #include "i8042.h"
#include "ps2_keyboard.h" #include "ps2_keyboard.h"
#include "ps2_mouse.h" #include "ps2_mouse.h"
@ -26,31 +29,39 @@
using namespace Genode; using namespace Genode;
int main(int argc, char **argv) struct Main
{ {
I8042 i8042; Server::Entrypoint &ep;
Serial_interface *kbd = i8042.kbd_interface(); I8042 i8042;
Serial_interface *aux = i8042.aux_interface(); Input::Session_component session;
Input::Root_component root;
/* Ps2_mouse ps2_mouse;
* Initialize server entry point Ps2_keyboard ps2_keybd;
*/
enum { STACK_SIZE = 4096 };
static Cap_connection cap;
static Rpc_entrypoint ep(&cap, STACK_SIZE, "ps2_ep");
static Input::Session_component session; Irq_handler ps2_mouse_irq;
static Input::Root_component root(ep, session); Irq_handler ps2_keybd_irq;
Ps2_mouse ps2_mouse(*aux, session.event_queue()); Main(Server::Entrypoint &ep)
Ps2_keyboard ps2_keybd(*kbd, session.event_queue(), i8042.kbd_xlate()); : ep(ep), root(ep.rpc_ep(), session),
ps2_mouse(*i8042.aux_interface(), session.event_queue()),
ps2_keybd(*i8042.kbd_interface(), session.event_queue(),
i8042.kbd_xlate()),
ps2_mouse_irq(ep, 12, ps2_mouse),
ps2_keybd_irq(ep, 1, ps2_keybd)
{
env()->parent()->announce(ep.manage(root));
}
};
Irq_handler ps2_mouse_irq(12, ps2_mouse);
Irq_handler ps2_keybd_irq( 1, ps2_keybd);
env()->parent()->announce(ep.manage(&root)); /************
** Server **
************/
Genode::sleep_forever(); namespace Server {
return 0; char const *name() { return "ps2_drv_ep"; }
size_t stack_size() { return 1024*sizeof(long); }
void construct(Entrypoint &ep) { static Main server(ep); }
} }

View File

@ -1,6 +1,6 @@
TARGET = ps2_drv TARGET = ps2_drv
REQUIRES = x86 ps2 REQUIRES = x86 ps2
SRC_CC = main.cc SRC_CC = main.cc
LIBS = base LIBS = base server
INC_DIR = $(PRG_DIR)/.. INC_DIR = $(PRG_DIR)/..

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (C) 2013 Genode Labs GmbH * Copyright (C) 2015 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
@ -19,6 +19,7 @@
#include <base/printf.h> #include <base/printf.h>
#include <timer_session/connection.h> #include <timer_session/connection.h>
#include <block/component.h> #include <block/component.h>
#include <os/server.h>
/* local includes */ /* local includes */
#include <dwmmc.h> #include <dwmmc.h>
@ -54,6 +55,8 @@ class Block::Exynos5_driver : public Block::Driver
}; };
Server::Entrypoint &_ep;
/* display sub system registers */ /* display sub system registers */
Attached_io_mem_dataspace _mmio; Attached_io_mem_dataspace _mmio;
@ -64,10 +67,11 @@ class Block::Exynos5_driver : public Block::Driver
public: public:
Exynos5_driver(bool use_dma) Exynos5_driver(Server::Entrypoint &ep, bool use_dma)
: :
_ep(ep),
_mmio(MSH_BASE, MSH_SIZE), _mmio(MSH_BASE, MSH_SIZE),
_controller((addr_t)_mmio.local_addr<void>(), _controller(ep, (addr_t)_mmio.local_addr<void>(),
_delayer, use_dma), _delayer, use_dma),
_use_dma(use_dma) _use_dma(use_dma)
{ {

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (C) 2013 Genode Labs GmbH * Copyright (C) 2015 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
@ -318,7 +318,9 @@ struct Exynos5_msh_controller : private Dwmmc, Sd_card::Host_controller
Delayer &_delayer; Delayer &_delayer;
Sd_card::Card_info _card_info; Sd_card::Card_info _card_info;
Genode::Irq_connection _irq; Genode::Irq_connection _irq;
Genode::Signal_receiver _irq_rec;
Genode::Signal_context _irq_ctx;
Sd_card::Card_info _init() Sd_card::Card_info _init()
{ {
@ -464,10 +466,21 @@ struct Exynos5_msh_controller : private Dwmmc, Sd_card::Host_controller
return true; return true;
} }
void _wait_for_irq()
{
/*
* Acknowledge the IRQ first to implicitly activate
* receiving of further IRQ signals on the first usage
* of this method.
*/
_irq.ack_irq();
_irq_rec.wait_for_signal();
}
bool _wait_for_transfer_complete() bool _wait_for_transfer_complete()
{ {
while (1) { while (1) {
_irq.wait_for_irq(); _wait_for_irq();
if (read<Rintsts::Data_transfer_over>()) { if (read<Rintsts::Data_transfer_over>()) {
write<Rintsts>(~0U); write<Rintsts>(~0U);
@ -491,11 +504,13 @@ struct Exynos5_msh_controller : private Dwmmc, Sd_card::Host_controller
} }
} }
public: public:
enum { IRQ_NUMBER = Genode::Board_base::SDMMC0_IRQ }; enum { IRQ_NUMBER = Genode::Board_base::SDMMC0_IRQ };
Exynos5_msh_controller(Genode::addr_t const mmio_base, Delayer &delayer, Exynos5_msh_controller(Server::Entrypoint &ep,
Genode::addr_t const mmio_base, Delayer &delayer,
bool use_dma) bool use_dma)
: Dwmmc(mmio_base), : Dwmmc(mmio_base),
_idmac_desc_ds(Genode::env()->ram_session(), _idmac_desc_ds(Genode::env()->ram_session(),
@ -505,8 +520,10 @@ struct Exynos5_msh_controller : private Dwmmc, Sd_card::Host_controller
_idmac_desc_phys(Genode::Dataspace_client(_idmac_desc_ds.cap()).phys_addr()), _idmac_desc_phys(Genode::Dataspace_client(_idmac_desc_ds.cap()).phys_addr()),
_delayer(delayer), _card_info(_init()), _irq(IRQ_NUMBER) _delayer(delayer), _card_info(_init()), _irq(IRQ_NUMBER)
{ {
_irq.sigh(_irq_rec.manage(&_irq_ctx));
} }
~Exynos5_msh_controller() { _irq_rec.dissolve(&_irq_ctx); }
bool _issue_command(Sd_card::Command_base const &command) bool _issue_command(Sd_card::Command_base const &command)
{ {

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (C) 2013 Genode Labs GmbH * Copyright (C) 2015 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
@ -26,8 +26,12 @@ struct Main
struct Factory : Block::Driver_factory struct Factory : Block::Driver_factory
{ {
Server::Entrypoint &ep;
Factory(Server::Entrypoint &ep) : ep(ep) { }
Block::Driver *create() { Block::Driver *create() {
return new (Genode::env()->heap()) Block::Exynos5_driver(true); } return new (Genode::env()->heap()) Block::Exynos5_driver(ep, true); }
void destroy(Block::Driver *driver) { void destroy(Block::Driver *driver) {
Genode::destroy(Genode::env()->heap(), Genode::destroy(Genode::env()->heap(),
@ -38,7 +42,7 @@ struct Main
Block::Root root; Block::Root root;
Main(Server::Entrypoint &ep) Main(Server::Entrypoint &ep)
: ep(ep), regulator(Regulator::CLK_MMC0), : ep(ep), factory(ep), regulator(Regulator::CLK_MMC0),
root(ep, Genode::env()->heap(), factory) root(ep, Genode::env()->heap(), factory)
{ {
Genode::printf("--- Arndale eMMC card driver ---\n"); Genode::printf("--- Arndale eMMC card driver ---\n");

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (C) 2012-2013 Genode Labs GmbH * Copyright (C) 2012-2015 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
@ -16,6 +16,7 @@
#include <base/printf.h> #include <base/printf.h>
#include <timer_session/connection.h> #include <timer_session/connection.h>
#include <os/attached_ram_dataspace.h> #include <os/attached_ram_dataspace.h>
#include <os/server.h>
/* local includes */ /* local includes */
#include <driver.h> #include <driver.h>
@ -86,81 +87,93 @@ static void run_benchmark(Block::Driver &driver,
} }
int main(int argc, char **argv) struct Main
{ {
using namespace Genode; Main(Server::Entrypoint &ep)
printf("--- i.MX53 SD card benchmark ---\n");
bool const use_dma = true;
static Block::Imx53_driver driver(use_dma);
static Timer::Connection timer;
long const request_sizes[] = {
512, 1024, 2048, 4096, 8192, 16384, 32768, 64*1024, 128*1024, 0 };
/* total size of communication buffer */
size_t const buffer_size = 10 * 1024 * 1024;
/* allocate read/write buffer */
static Attached_ram_dataspace buffer(env()->ram_session(), buffer_size, Genode::UNCACHED);
char * const buffer_virt = buffer.local_addr<char>();
addr_t const buffer_phys = Dataspace_client(buffer.cap()).phys_addr();
/*
* Benchmark reading from SD card
*/
printf("\n-- reading from SD card --\n");
struct Read : Operation
{ {
void operator () (Block::Driver &driver, using namespace Genode;
addr_t number, size_t count, addr_t phys, char *virt)
{
Block::Packet_descriptor p;
if (driver.dma_enabled())
driver.read_dma(number, count, phys, p);
else
driver.read(number, count, virt, p);
}
} read_operation;
for (unsigned i = 0; request_sizes[i]; i++) { printf("--- i.MX53 SD card benchmark ---\n");
run_benchmark(driver, timer, buffer_virt, buffer_phys, buffer_size,
request_sizes[i], read_operation); bool const use_dma = true;
static Block::Imx53_driver driver(use_dma);
static Timer::Connection timer;
long const request_sizes[] = {
512, 1024, 2048, 4096, 8192, 16384, 32768, 64*1024, 128*1024, 0 };
/* total size of communication buffer */
size_t const buffer_size = 10 * 1024 * 1024;
/* allocate read/write buffer */
static Attached_ram_dataspace buffer(env()->ram_session(), buffer_size, Genode::UNCACHED);
char * const buffer_virt = buffer.local_addr<char>();
addr_t const buffer_phys = Dataspace_client(buffer.cap()).phys_addr();
/*
* Benchmark reading from SD card
*/
printf("\n-- reading from SD card --\n");
struct Read : Operation
{
void operator () (Block::Driver &driver,
addr_t number, size_t count, addr_t phys, char *virt)
{
Block::Packet_descriptor p;
if (driver.dma_enabled())
driver.read_dma(number, count, phys, p);
else
driver.read(number, count, virt, p);
}
} read_operation;
for (unsigned i = 0; request_sizes[i]; i++) {
run_benchmark(driver, timer, buffer_virt, buffer_phys, buffer_size,
request_sizes[i], read_operation);
}
/*
* Benchmark writing to SD card
*
* We write back the content of the buffer, which we just filled during the
* read benchmark. If both read and write succeed, the SD card will retain
* its original content.
*/
printf("\n-- writing to SD card --\n");
struct Write : Operation
{
void operator () (Block::Driver &driver,
addr_t number, size_t count, addr_t phys, char *virt)
{
Block::Packet_descriptor p;
if (driver.dma_enabled())
driver.write_dma(number, count, phys, p);
else
driver.write(number, count, virt, p);
}
} write_operation;
for (unsigned i = 0; request_sizes[i]; i++)
run_benchmark(driver, timer, buffer_virt, buffer_phys, buffer_size,
request_sizes[i], write_operation);
printf("\n--- i.MX53 SD card benchmark finished ---\n");
} }
};
/*
* Benchmark writing to SD card
*
* We write back the content of the buffer, which we just filled during the
* read benchmark. If both read and write succeed, the SD card will retain
* its original content.
*/
printf("\n-- writing to SD card --\n"); /************
** Server **
************/
struct Write : Operation namespace Server {
{ char const *name() { return "sd_card_bench_ep"; }
void operator () (Block::Driver &driver, size_t stack_size() { return 2*1024*sizeof(long); }
addr_t number, size_t count, addr_t phys, char *virt) void construct(Entrypoint &ep) { static Main server(ep); }
{
Block::Packet_descriptor p;
if (driver.dma_enabled())
driver.write_dma(number, count, phys, p);
else
driver.write(number, count, virt, p);
}
} write_operation;
for (unsigned i = 0; request_sizes[i]; i++)
run_benchmark(driver, timer, buffer_virt, buffer_phys, buffer_size,
request_sizes[i], write_operation);
printf("\n--- i.MX53 SD card benchmark finished ---\n");
sleep_forever();
return 0;
} }

View File

@ -1,5 +1,5 @@
TARGET = sd_card_bench TARGET = sd_card_bench
REQUIRES = imx53 REQUIRES = imx53
SRC_CC = main.cc SRC_CC = main.cc
LIBS = base LIBS = base server
INC_DIR += $(PRG_DIR)/.. $(PRG_DIR)/../.. INC_DIR += $(PRG_DIR)/.. $(PRG_DIR)/../..

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (C) 2012-2013 Genode Labs GmbH * Copyright (C) 2012-2015 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
@ -20,6 +20,7 @@
#include <timer_session/connection.h> #include <timer_session/connection.h>
#include <block/component.h> #include <block/component.h>
#include <drivers/board_base.h> #include <drivers/board_base.h>
#include <os/server.h>
/* local includes */ /* local includes */
#include <esdhcv2.h> #include <esdhcv2.h>

View File

@ -414,11 +414,13 @@ struct Esdhcv2_controller : private Esdhcv2, public Sd_card::Host_controller
BURST_WORDS = 8, BURST_WORDS = 8,
}; };
Genode::Irq_connection _irq; Genode::Irq_connection _irq;
Delayer & _delayer; Genode::Signal_receiver _irq_rec;
Sd_card::Card_info _card_info; Genode::Signal_context _irq_ctx;
bool const _use_dma; Delayer & _delayer;
Adma2::Table _adma2_table; Sd_card::Card_info _card_info;
bool const _use_dma;
Adma2::Table _adma2_table;
/** /**
* Print 'err' and throw detection-error exception * Print 'err' and throw detection-error exception
@ -569,6 +571,20 @@ struct Esdhcv2_controller : private Esdhcv2, public Sd_card::Host_controller
return card_info; return card_info;
} }
/**
* Wait until we received the IRQ signal
*/
void _wait_for_irq()
{
/*
* Acknowledge the IRQ first to implicitly activate
* receiving of further IRQ signals on the first usage
* of this method.
*/
_irq.ack_irq();
_irq_rec.wait_for_signal();
}
/* /*
* Wait till sending a new command is allowed * Wait till sending a new command is allowed
* *
@ -596,7 +612,7 @@ struct Esdhcv2_controller : private Esdhcv2, public Sd_card::Host_controller
*/ */
bool _wait_for_cmd_complete() bool _wait_for_cmd_complete()
{ {
_irq.wait_for_irq(); _wait_for_irq();
if (read<Irqstat>() != Irqstat::Cc::reg_mask()) { if (read<Irqstat>() != Irqstat::Cc::reg_mask()) {
PWRN("received unexpected host signal"); PWRN("received unexpected host signal");
reset_command(_delayer); reset_command(_delayer);
@ -634,7 +650,7 @@ struct Esdhcv2_controller : private Esdhcv2, public Sd_card::Host_controller
bool _wait_for_mbc_complete(bool const r) bool _wait_for_mbc_complete(bool const r)
{ {
/* wait for a signal */ /* wait for a signal */
_irq.wait_for_irq(); _wait_for_irq();
Irqstat::access_t const irq = read<Irqstat>(); Irqstat::access_t const irq = read<Irqstat>();
/* /*
@ -741,9 +757,13 @@ struct Esdhcv2_controller : private Esdhcv2, public Sd_card::Host_controller
Esdhcv2_controller(addr_t const mmio_base, unsigned const irq, Esdhcv2_controller(addr_t const mmio_base, unsigned const irq,
Delayer & delayer, bool const use_dma) Delayer & delayer, bool const use_dma)
: :
Esdhcv2(mmio_base), _irq(irq), _delayer(delayer), Esdhcv2(mmio_base), _irq(irq),
_card_info(_init()), _use_dma(use_dma) _delayer(delayer), _card_info(_init()), _use_dma(use_dma)
{ } {
_irq.sigh(_irq_rec.manage(&_irq_ctx));
}
~Esdhcv2_controller() { _irq_rec.dissolve(&_irq_ctx); }
/**************************************** /****************************************

View File

@ -25,6 +25,10 @@ struct Main
struct Factory : Block::Driver_factory struct Factory : Block::Driver_factory
{ {
Server::Entrypoint &ep;
Factory(Server::Entrypoint &ep) : ep(ep) { }
Block::Driver *create() { Block::Driver *create() {
return new (Genode::env()->heap()) Block::Imx53_driver(true); } return new (Genode::env()->heap()) Block::Imx53_driver(true); }
@ -36,7 +40,7 @@ struct Main
Block::Root root; Block::Root root;
Main(Server::Entrypoint &ep) Main(Server::Entrypoint &ep)
: ep(ep), root(ep, Genode::env()->heap(), factory) : ep(ep), factory(ep), root(ep, Genode::env()->heap(), factory)
{ {
Genode::printf("--- Imx53 SD card driver ---\n"); Genode::printf("--- Imx53 SD card driver ---\n");
@ -54,4 +58,3 @@ namespace Server {
size_t stack_size() { return 2*1024*sizeof(long); } size_t stack_size() { return 2*1024*sizeof(long); }
void construct(Entrypoint &ep) { static Main server(ep); } void construct(Entrypoint &ep) { static Main server(ep); }
} }

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (C) 2012-2013 Genode Labs GmbH * Copyright (C) 2012-2015 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
@ -77,80 +77,92 @@ static void run_benchmark(Block::Driver &driver,
} }
int main(int argc, char **argv) struct Main
{ {
using namespace Genode; Main(Server::Entrypoint &ep)
printf("--- OMAP4 SD card benchmark ---\n");
bool const use_dma = false;
static Block::Omap4_driver driver(use_dma);
static Timer::Connection timer;
long const request_sizes[] = {
512, 1024, 2048, 4096, 8192, 16384, 32768, 64*1024, 128*1024, 0 };
/* total size of communication buffer */
size_t const buffer_size = 10*1024*1024;
/* allocate read/write buffer */
static Attached_ram_dataspace buffer(env()->ram_session(), buffer_size, Genode::UNCACHED);
char * const buffer_virt = buffer.local_addr<char>();
addr_t const buffer_phys = Dataspace_client(buffer.cap()).phys_addr();
/*
* Benchmark reading from SD card
*/
printf("\n-- reading from SD card --\n");
struct Read : Operation
{ {
void operator () (Block::Driver &driver, using namespace Genode;
addr_t number, size_t count, addr_t phys, char *virt)
printf("--- OMAP4 SD card benchmark ---\n");
bool const use_dma = false;
static Block::Omap4_driver driver(use_dma);
static Timer::Connection timer;
long const request_sizes[] = {
512, 1024, 2048, 4096, 8192, 16384, 32768, 64*1024, 128*1024, 0 };
/* total size of communication buffer */
size_t const buffer_size = 10*1024*1024;
/* allocate read/write buffer */
static Attached_ram_dataspace buffer(env()->ram_session(), buffer_size, Genode::UNCACHED);
char * const buffer_virt = buffer.local_addr<char>();
addr_t const buffer_phys = Dataspace_client(buffer.cap()).phys_addr();
/*
* Benchmark reading from SD card
*/
printf("\n-- reading from SD card --\n");
struct Read : Operation
{ {
Block::Packet_descriptor p; void operator () (Block::Driver &driver,
if (driver.dma_enabled()) addr_t number, size_t count, addr_t phys, char *virt)
driver.read_dma(number, count, phys, p); {
else Block::Packet_descriptor p;
driver.read(number, count, virt, p); if (driver.dma_enabled())
} driver.read_dma(number, count, phys, p);
} read_operation; else
driver.read(number, count, virt, p);
}
} read_operation;
for (unsigned i = 0; request_sizes[i]; i++) for (unsigned i = 0; request_sizes[i]; i++)
run_benchmark(driver, timer, buffer_virt, buffer_phys, buffer_size, run_benchmark(driver, timer, buffer_virt, buffer_phys, buffer_size,
request_sizes[i], read_operation); request_sizes[i], read_operation);
/* /*
* Benchmark writing to SD card * Benchmark writing to SD card
* *
* We write back the content of the buffer, which we just filled during the * We write back the content of the buffer, which we just filled during the
* read benchmark. If both read and write succeed, the SD card will retain * read benchmark. If both read and write succeed, the SD card will retain
* its original content. * its original content.
*/ */
printf("\n-- writing to SD card --\n"); printf("\n-- writing to SD card --\n");
struct Write : Operation struct Write : Operation
{
void operator () (Block::Driver &driver,
addr_t number, size_t count, addr_t phys, char *virt)
{ {
Block::Packet_descriptor p; void operator () (Block::Driver &driver,
if (driver.dma_enabled()) addr_t number, size_t count, addr_t phys, char *virt)
driver.write_dma(number, count, phys, p); {
else Block::Packet_descriptor p;
driver.write(number, count, virt, p); if (driver.dma_enabled())
} driver.write_dma(number, count, phys, p);
} write_operation; else
driver.write(number, count, virt, p);
}
} write_operation;
for (unsigned i = 0; request_sizes[i]; i++) for (unsigned i = 0; request_sizes[i]; i++)
run_benchmark(driver, timer, buffer_virt, buffer_phys, buffer_size, run_benchmark(driver, timer, buffer_virt, buffer_phys, buffer_size,
request_sizes[i], write_operation); request_sizes[i], write_operation);
printf("\n--- OMAP4 SD card benchmark finished ---\n"); printf("\n--- OMAP4 SD card benchmark finished ---\n");
sleep_forever(); }
return 0; };
/************
** Server **
************/
namespace Server {
char const *name() { return "sd_card_bench_ep"; }
size_t stack_size() { return 2*1024*sizeof(long); }
void construct(Entrypoint &ep) { static Main server(ep); }
} }

View File

@ -1,5 +1,5 @@
TARGET = sd_card_bench TARGET = sd_card_bench
REQUIRES = omap4 REQUIRES = omap4
SRC_CC = main.cc SRC_CC = main.cc
LIBS = base LIBS = base server
INC_DIR += $(PRG_DIR)/.. $(PRG_DIR)/../.. INC_DIR += $(PRG_DIR)/.. $(PRG_DIR)/../..

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (C) 2012-2013 Genode Labs GmbH * Copyright (C) 2012-2015 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
@ -19,6 +19,7 @@
#include <base/printf.h> #include <base/printf.h>
#include <timer_session/connection.h> #include <timer_session/connection.h>
#include <block/component.h> #include <block/component.h>
#include <os/server.h>
/* local includes */ /* local includes */
#include <mmchs.h> #include <mmchs.h>

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (C) 2012-2013 Genode Labs GmbH * Copyright (C) 2012-2015 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
@ -25,6 +25,10 @@ struct Main
struct Factory : Block::Driver_factory struct Factory : Block::Driver_factory
{ {
Server::Entrypoint &ep;
Factory(Server::Entrypoint &ep) : ep(ep) { }
Block::Driver *create() { Block::Driver *create() {
return new (Genode::env()->heap()) Block::Omap4_driver(true); } return new (Genode::env()->heap()) Block::Omap4_driver(true); }
@ -36,7 +40,7 @@ struct Main
Block::Root root; Block::Root root;
Main(Server::Entrypoint &ep) Main(Server::Entrypoint &ep)
: ep(ep), root(ep, Genode::env()->heap(), factory) : ep(ep), factory(ep), root(ep, Genode::env()->heap(), factory)
{ {
Genode::printf("--- OMAP4 SD card driver ---\n"); Genode::printf("--- OMAP4 SD card driver ---\n");
@ -54,4 +58,3 @@ namespace Server {
size_t stack_size() { return 2*1024*sizeof(long); } size_t stack_size() { return 2*1024*sizeof(long); }
void construct(Entrypoint &ep) { static Main server(ep); } void construct(Entrypoint &ep) { static Main server(ep); }
} }

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (C) 2012-2013 Genode Labs GmbH * Copyright (C) 2012-2015 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
@ -500,7 +500,9 @@ struct Omap4_hsmmc_controller : private Mmchs, public Sd_card::Host_controller
Adma_desc::access_t * const _adma_desc; Adma_desc::access_t * const _adma_desc;
Genode::addr_t const _adma_desc_phys; Genode::addr_t const _adma_desc_phys;
Genode::Irq_connection _irq; Genode::Irq_connection _irq;
Genode::Signal_receiver _irq_rec;
Genode::Signal_context _irq_ctx;
Sd_card::Card_info _init() Sd_card::Card_info _init()
{ {
@ -729,7 +731,12 @@ struct Omap4_hsmmc_controller : private Mmchs, public Sd_card::Host_controller
* running processes. * running processes.
*/ */
for (;;) { for (;;) {
_irq.wait_for_irq(); /*
* We ack the IRQ first to implicitly active receiving
* IRQ signals when entering this loop for the first time.
*/
_irq.ack_irq();
_irq_rec.wait_for_signal();
/* check for transfer completion */ /* check for transfer completion */
if (read<Stat::Tc>() == 1) { if (read<Stat::Tc>() == 1) {
@ -748,6 +755,7 @@ struct Omap4_hsmmc_controller : private Mmchs, public Sd_card::Host_controller
} }
} }
public: public:
enum { IRQ_NUMBER = Genode::Board_base::HSMMC_IRQ }; enum { IRQ_NUMBER = Genode::Board_base::HSMMC_IRQ };
@ -768,7 +776,11 @@ struct Omap4_hsmmc_controller : private Mmchs, public Sd_card::Host_controller
_adma_desc(_adma_desc_ds.local_addr<Adma_desc::access_t>()), _adma_desc(_adma_desc_ds.local_addr<Adma_desc::access_t>()),
_adma_desc_phys(Genode::Dataspace_client(_adma_desc_ds.cap()).phys_addr()), _adma_desc_phys(Genode::Dataspace_client(_adma_desc_ds.cap()).phys_addr()),
_irq(IRQ_NUMBER) _irq(IRQ_NUMBER)
{ } {
_irq.sigh(_irq_rec.manage(&_irq_ctx));
}
~Omap4_hsmmc_controller() { _irq_rec.dissolve(&_irq_ctx); }
/**************************************** /****************************************

27
repos/os/src/drivers/timer/hw/platform_timer.h Executable file → Normal file
View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (C) 2012-2013 Genode Labs GmbH * Copyright (C) 2012-2015 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
@ -16,6 +16,7 @@
/* Genode includes */ /* Genode includes */
#include <irq_session/connection.h> #include <irq_session/connection.h>
#include <os/server.h>
/* Local includes */ /* Local includes */
#include <platform_timer_base.h> #include <platform_timer_base.h>
@ -30,10 +31,13 @@ class Platform_timer : public Platform_timer_base,
enum { MAX_TIMER_IRQS_PER_MS = 1 }; enum { MAX_TIMER_IRQS_PER_MS = 1 };
unsigned long const _max_timeout_us; /* maximum timeout in microsecs */ unsigned long const _max_timeout_us; /* maximum timeout in microsecs */
unsigned long mutable _curr_time_us; /* accumulate already measured timeouts */ unsigned long mutable _curr_time_us; /* accumulate already measured timeouts */
unsigned long mutable _init_value; /* mark last processed timer value */ unsigned long mutable _init_value; /* mark last processed timer value */
Genode::Lock mutable _update_curr_time_lock; /* serialize curr_time access */ Genode::Lock mutable _update_curr_time_lock; /* serialize curr_time access */
Genode::Signal_receiver _irq_rec;
Genode::Signal_context _irq_ctx;
public: public:
@ -45,7 +49,12 @@ class Platform_timer : public Platform_timer_base,
Irq_connection(Platform_timer_base::IRQ), Irq_connection(Platform_timer_base::IRQ),
_max_timeout_us(tics_to_us(max_value())), _max_timeout_us(tics_to_us(max_value())),
_curr_time_us(0), _init_value(0) _curr_time_us(0), _init_value(0)
{ } {
Irq_connection::sigh(_irq_rec.manage(&_irq_ctx));
Irq_connection::ack_irq();
}
~Platform_timer() { _irq_rec.dissolve(&_irq_ctx); }
/** /**
* Refresh and return our instance-own "now"-time in microseconds * Refresh and return our instance-own "now"-time in microseconds
@ -109,7 +118,11 @@ class Platform_timer : public Platform_timer_base,
/** /**
* Await the lastly scheduled timeout * Await the lastly scheduled timeout
*/ */
void wait_for_timeout(Genode::Thread_base *) { wait_for_irq(); } void wait_for_timeout(Genode::Thread_base *)
{
_irq_rec.wait_for_signal();
Irq_connection::ack_irq();
}
}; };
#endif /* _OS__SRC__DRIVERS__TIMER__HW__PLATFORM_TIMER_H_ */ #endif /* _OS__SRC__DRIVERS__TIMER__HW__PLATFORM_TIMER_H_ */

View File

@ -14,12 +14,15 @@
#ifndef _TIMER_ROOT_H_ #ifndef _TIMER_ROOT_H_
#define _TIMER_ROOT_H_ #define _TIMER_ROOT_H_
/* Genode includes */
#include <util/arg_string.h> #include <util/arg_string.h>
#include <base/printf.h> #include <base/printf.h>
#include <base/heap.h> #include <base/heap.h>
#include <root/component.h> #include <root/component.h>
#include <cap_session/cap_session.h> #include <cap_session/cap_session.h>
#include <os/server.h>
/* local includes */
#include "timer_session_component.h" #include "timer_session_component.h"
@ -56,12 +59,12 @@ class Timer::Root_component : public Genode::Root_component<Session_component>
* The 'cap' argument is not used by the single-threaded server * The 'cap' argument is not used by the single-threaded server
* variant. * variant.
*/ */
Root_component(Genode::Rpc_entrypoint *session_ep, Root_component(Server::Entrypoint &ep,
Genode::Allocator *md_alloc, Genode::Allocator *md_alloc,
Genode::Cap_session *cap) Genode::Cap_session *cap)
: :
Genode::Root_component<Session_component>(session_ep, md_alloc), Genode::Root_component<Session_component>(&ep.rpc_ep(), md_alloc),
_timeout_scheduler(&_platform_timer, session_ep) _timeout_scheduler(&_platform_timer, &ep.rpc_ep())
{ } { }
}; };

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (C) 2009-2013 Genode Labs GmbH * Copyright (C) 2009-2015 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
@ -14,8 +14,9 @@
#ifndef _PLATFORM_TIMER_H_ #ifndef _PLATFORM_TIMER_H_
#define _PLATFORM_TIMER_H_ #define _PLATFORM_TIMER_H_
/* Genode inludes **/ /* Genode inludes */
#include <base/thread.h> #include <base/thread.h>
#include <os/server.h>
class Platform_timer class Platform_timer

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (C) 2009-2013 Genode Labs GmbH * Copyright (C) 2009-2015 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
@ -14,8 +14,10 @@
#ifndef _PLATFORM_TIMER_H_ #ifndef _PLATFORM_TIMER_H_
#define _PLATFORM_TIMER_H_ #define _PLATFORM_TIMER_H_
/* Genode includes */
#include <io_port_session/connection.h> #include <io_port_session/connection.h>
#include <irq_session/connection.h> #include <irq_session/connection.h>
#include <os/server.h>
class Platform_timer class Platform_timer
{ {
@ -64,6 +66,8 @@ class Platform_timer
unsigned long mutable _curr_time_usec; unsigned long mutable _curr_time_usec;
Genode::uint16_t mutable _counter_init_value; Genode::uint16_t mutable _counter_init_value;
bool mutable _handled_wrap; bool mutable _handled_wrap;
Genode::Signal_receiver _irq_rec;
Genode::Signal_context _irq_ctx;
/** /**
* Set PIT counter value * Set PIT counter value
@ -111,8 +115,13 @@ class Platform_timer
/* operate PIT in one-shot mode */ /* operate PIT in one-shot mode */
_io_port.outb(PIT_CMD_PORT, PIT_CMD_SELECT_CHANNEL_0 | _io_port.outb(PIT_CMD_PORT, PIT_CMD_SELECT_CHANNEL_0 |
PIT_CMD_ACCESS_LO_HI | PIT_CMD_MODE_IRQ); PIT_CMD_ACCESS_LO_HI | PIT_CMD_MODE_IRQ);
_timer_irq.sigh(_irq_rec.manage(&_irq_ctx));
_timer_irq.ack_irq();
} }
~Platform_timer() { _irq_rec.dissolve(&_irq_ctx); }
/** /**
* Return current time-counter value in microseconds * Return current time-counter value in microseconds
* *
@ -188,7 +197,8 @@ class Platform_timer
*/ */
void wait_for_timeout(Genode::Thread_base *blocking_thread) void wait_for_timeout(Genode::Thread_base *blocking_thread)
{ {
_timer_irq.wait_for_irq(); _irq_rec.wait_for_signal();
_timer_irq.ack_irq();
} }
}; };

View File

@ -5,50 +5,52 @@
*/ */
/* /*
* Copyright (C) 2006-2013 Genode Labs GmbH * Copyright (C) 2006-2015 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
*/ */
/* Genode includes */
#include <base/env.h> #include <base/env.h>
#include <base/sleep.h> #include <base/sleep.h>
#include <base/heap.h> #include <base/heap.h>
#include <cap_session/connection.h> #include <cap_session/connection.h>
#include <os/server.h>
/* local includes */
#include "timer_root.h" #include "timer_root.h"
using namespace Genode; using namespace Genode;
using namespace Timer; using namespace Timer;
/** struct Main
* Main program
*/
int main(int argc, char **argv)
{ {
/* Server::Entrypoint &ep;
* Initialize server entry point that serves the root interface. Sliced_heap sliced_heap;
*/ Timer::Root_component root;
static Cap_connection cap;
static Rpc_entrypoint ep(&cap, STACK_SIZE, "timer_ep");
/* Main(Server::Entrypoint &ep)
* Use sliced heap to allocate each session component at a separate :
* dataspace. ep(ep),
*/ sliced_heap(Genode::env()->ram_session(), Genode::env()->rm_session()),
static Sliced_heap sliced_heap(env()->ram_session(), env()->rm_session()); root(ep, &sliced_heap, 0)
{
/*
* Announce timer service at our parent.
*/
env()->parent()->announce(ep.manage(root));
}
};
/*
* Create root interface for timer service
*/
static Timer::Root_component timer_root(&ep, &sliced_heap, &cap);
/* /************
* Announce timer service at our parent. ** Server **
*/ ************/
env()->parent()->announce(ep.manage(&timer_root));
sleep_forever(); namespace Server {
return 0; char const *name() { return "timer_drv_ep"; }
size_t stack_size() { return 1024*sizeof(long); }
void construct(Entrypoint &ep) { static Main server(ep); }
} }

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (C) 2014-2014 Genode Labs GmbH * Copyright (C) 2014-2015 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
@ -14,7 +14,9 @@
#ifndef _PLATFORM_TIMER_H_ #ifndef _PLATFORM_TIMER_H_
#define _PLATFORM_TIMER_H_ #define _PLATFORM_TIMER_H_
/* Genode includes */
#include <os/attached_rom_dataspace.h> #include <os/attached_rom_dataspace.h>
#include <os/server.h>
#include <trace/timestamp.h> #include <trace/timestamp.h>
class Platform_timer class Platform_timer

View File

@ -6,7 +6,7 @@
/* /*
* Copyright (C) 2012 Ksys Labs LLC * Copyright (C) 2012 Ksys Labs LLC
* Copyright (C) 2012-2013 Genode Labs GmbH * Copyright (C) 2012-2015 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
@ -15,10 +15,12 @@
#ifndef _GPIO_TEST_H_ #ifndef _GPIO_TEST_H_
#define _GPIO_TEST_H_ #define _GPIO_TEST_H_
#include <gpio_session/connection.h> /* Genode includes */
#include <base/signal.h>
#include <util/mmio.h>
#include <base/printf.h> #include <base/printf.h>
#include <base/signal.h>
#include <gpio_session/connection.h>
#include <irq_session/client.h>
#include <util/mmio.h>
using namespace Genode; using namespace Genode;
@ -63,7 +65,6 @@ Gpio_test::Gpio_test()
{ {
/* initialize GPIO_121 */ /* initialize GPIO_121 */
_gpio_button.debouncing(31*100); _gpio_button.debouncing(31*100);
_gpio_button.irq_sigh(sig_rec.manage(&sig_ctx));
} }
@ -102,35 +103,49 @@ bool Gpio_test::irq_test()
{ {
printf("---------- IRQ test ----------\n"); printf("---------- IRQ test ----------\n");
_gpio_button.irq_type(Gpio::Session::FALLING_EDGE); {
_gpio_button.irq_enable(true); Genode::Irq_session_client
irq(_gpio_button.irq_session(Gpio::Session::FALLING_EDGE));
irq.sigh(sig_rec.manage(&sig_ctx));
/*
* Before any IRQs will be delivered to us, we have to signalize
* that we are ready to handle them by calling 'ack_irq()'.
*/
irq.ack_irq();
_gpio_led1.write(true); _gpio_led1.write(true);
_gpio_led2.write(false); _gpio_led2.write(false);
printf("\nPush and hold button...\n"); printf("\nPush and hold button...\n");
wait_for_signal(); wait_for_signal();
irq.ack_irq();
_gpio_button.irq_enable(false); }
printf("OK\n"); printf("OK\n");
_gpio_button.irq_type(Gpio::Session::RISING_EDGE); {
_gpio_button.irq_enable(true); Genode::Irq_session_client
irq(_gpio_button.irq_session(Gpio::Session::RISING_EDGE));
irq.sigh(sig_rec.manage(&sig_ctx));
_gpio_led1.write(false); _gpio_led1.write(false);
_gpio_led2.write(true); _gpio_led2.write(true);
printf("\nRelease button...\n"); printf("\nRelease button...\n");
wait_for_signal(); wait_for_signal();
irq.ack_irq();
_gpio_button.irq_enable(false); }
printf("OK\n"); printf("OK\n");
_gpio_button.irq_type(Gpio::Session::HIGH_LEVEL); {
Genode::Irq_session_client
irq(_gpio_button.irq_session(Gpio::Session::HIGH_LEVEL));
irq.sigh(sig_rec.manage(&sig_ctx));
}
return true; return true;
} }