usb: use irq via platform driver or directly

Issue #1471
This commit is contained in:
Alexander Boettcher 2015-04-29 14:00:33 +02:00 committed by Christian Helmuth
parent 6dd9d349fc
commit a58bc84d3e
6 changed files with 101 additions and 37 deletions

View File

@ -18,6 +18,7 @@
#include <regulator/consts.h> #include <regulator/consts.h>
#include <regulator_session/connection.h> #include <regulator_session/connection.h>
#include <timer_session/connection.h> #include <timer_session/connection.h>
#include <irq_session/connection.h>
#include <util/mmio.h> #include <util/mmio.h>
/* Emulation */ /* Emulation */
@ -363,3 +364,15 @@ void platform_hcd_init(Services *services)
if (services->xhci) if (services->xhci)
xhci_setup(services); xhci_setup(services);
} }
Genode::Irq_session_capability platform_irq_activate(int irq)
{
try {
Genode::Irq_connection conn(irq);
conn.on_destruction(Genode::Irq_connection::KEEP_OPEN);
return conn;
} catch (...) { }
return Genode::Irq_session_capability();
}

View File

@ -17,6 +17,7 @@
#include <drivers/board_base.h> #include <drivers/board_base.h>
#include <gpio_session/connection.h> #include <gpio_session/connection.h>
#include <io_mem_session/connection.h> #include <io_mem_session/connection.h>
#include <irq_session/connection.h>
#include <util/mmio.h> #include <util/mmio.h>
#include <extern_c_begin.h> #include <extern_c_begin.h>
@ -320,3 +321,14 @@ void platform_hcd_init(Services *services)
platform_device_register(pdev); platform_device_register(pdev);
} }
Genode::Irq_session_capability platform_irq_activate(int irq)
{
try {
Genode::Irq_connection conn(irq);
conn.on_destruction(Genode::Irq_connection::KEEP_OPEN);
return conn;
} catch (...) { }
return Genode::Irq_session_capability();
}

View File

@ -13,6 +13,7 @@
/* Genode includes */ /* Genode includes */
#include <io_mem_session/connection.h> #include <io_mem_session/connection.h>
#include <irq_session/connection.h>
#include <util/mmio.h> #include <util/mmio.h>
#include <platform_session/connection.h> #include <platform_session/connection.h>
@ -228,3 +229,15 @@ void platform_hcd_init(Services *services)
platform_device_register(pdev); platform_device_register(pdev);
} }
Genode::Irq_session_capability platform_irq_activate(int irq)
{
try {
Genode::Irq_connection conn(irq);
conn.on_destruction(Genode::Irq_connection::KEEP_OPEN);
return conn;
} catch (...) { }
return Genode::Irq_session_capability();
}

View File

@ -19,6 +19,8 @@
#include <base/printf.h> #include <base/printf.h>
#include <os/config.h> #include <os/config.h>
#include <util/xml_node.h> #include <util/xml_node.h>
#include <os/signal_rpc_dispatcher.h>
#include <irq_session/capability.h>
struct Services struct Services
{ {
@ -111,5 +113,6 @@ struct Services
}; };
void platform_hcd_init(Services *services); void platform_hcd_init(Services *services);
Genode::Irq_session_capability platform_irq_activate(int irq);
#endif /* _PLATFORM_H_ */ #endif /* _PLATFORM_H_ */

View File

@ -11,9 +11,13 @@
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
*/ */
/* Genode inludes */ /* Genode base includes */
#include <ram_session/client.h> #include <ram_session/client.h>
#include <base/object_pool.h> #include <base/object_pool.h>
#include <irq_session/connection.h>
/* Genode os includes */
#include <os/server.h>
#include <pci_session/connection.h> #include <pci_session/connection.h>
#include <pci_device/client.h> #include <pci_device/client.h>
@ -29,7 +33,7 @@ struct bus_type pci_bus_type;
/** /**
* Scan PCI bus and probe for HCDs * Scan PCI bus and probe for HCDs
*/ */
class Pci_driver class Pci_driver : public Genode::List<Pci_driver>::Element
{ {
private: private:
@ -53,9 +57,12 @@ class Pci_driver
{ {
using namespace Pci; using namespace Pci;
_dev = new (Genode::env()->heap()) pci_dev;
Device_client client(_cap); Device_client client(_cap);
uint8_t bus, dev, func;
client.bus_address(&bus, &dev, &func);
_dev = new (Genode::env()->heap()) pci_dev;
_dev->devfn = ((uint16_t)bus << 8) | (0xff & PCI_DEVFN(dev, func));
_dev->vendor = client.vendor_id(); _dev->vendor = client.vendor_id();
_dev->device = client.device_id(); _dev->device = client.device_id();
_dev->class_ = client.class_code(); _dev->class_ = client.class_code();
@ -105,6 +112,8 @@ class Pci_driver
/* enable bus master */ /* enable bus master */
cmd |= 0x4; cmd |= 0x4;
client.config_write(CMD, cmd, Device::ACCESS_16BIT); client.config_write(CMD, cmd, Device::ACCESS_16BIT);
_drivers().insert(this);
} }
/** /**
@ -135,6 +144,12 @@ class Pci_driver
} }
} }
static Genode::List<Pci_driver> & _drivers()
{
static Genode::List<Pci_driver> _list;
return _list;
}
public: public:
Pci_driver(pci_driver *drv, Pci::Device_capability cap, Pci_driver(pci_driver *drv, Pci::Device_capability cap,
@ -157,6 +172,8 @@ class Pci_driver
dde_kit_release_io(r->start, (r->end - r->start) + 1); dde_kit_release_io(r->start, (r->end - r->start) + 1);
} }
_drivers().remove(this);
destroy(Genode::env()->heap(), _dev); destroy(Genode::env()->heap(), _dev);
} }
@ -176,8 +193,20 @@ class Pci_driver
Pci::Device_client client(_cap); Pci::Device_client client(_cap);
client.config_write(devfn, val, _access_size(val)); client.config_write(devfn, val, _access_size(val));
} }
};
static Genode::Irq_session_capability irq_cap(unsigned irq)
{
for (Pci_driver *d = _drivers().first(); d; d = d->next()) {
if (d->_dev && d->_dev->irq != irq)
continue;
Pci::Device_client client(d->_cap);
return client.irq(0);
}
return Genode::Irq_session_capability();
}
};
/******************************** /********************************
** Backend memory definitions ** ** Backend memory definitions **
@ -401,3 +430,13 @@ void Backend_memory::free(Genode::Ram_dataspace_capability cap)
memory_pool.remove_locked(o); memory_pool.remove_locked(o);
destroy(env()->heap(), o); destroy(env()->heap(), o);
} }
/*****************************************
** Platform specific irq cap discovery **
*****************************************/
Genode::Irq_session_capability platform_irq_activate(int irq)
{
return Pci_driver::irq_cap(irq);
}

View File

@ -12,19 +12,17 @@
*/ */
#include <signal.h> #include <signal.h>
#include <irq_session/client.h>
#include <extern_c_begin.h> #include <extern_c_begin.h>
#include <lx_emul.h> #include <lx_emul.h>
#include <extern_c_end.h> #include <extern_c_end.h>
extern "C" { #include <platform.h>
#include <dde_kit/interrupt.h>
}
#include<timer_session/connection.h>
/* our local incarnation of sender and receiver */ /* our local incarnation of sender and receiver */
static Signal_helper *_signal = 0; static Signal_helper *_signal = 0;
static Genode::Lock _irq_sync(Genode::Lock::LOCKED);
/** /**
* This contains the Linux-driver handlers * This contains the Linux-driver handlers
@ -52,6 +50,8 @@ class Irq_context : public Genode::List<Irq_context>::Element
unsigned int _irq; /* IRQ number */ unsigned int _irq; /* IRQ number */
Genode::List<Irq_handler> _handler_list; /* List of registered handlers */ Genode::List<Irq_handler> _handler_list; /* List of registered handlers */
Genode::Signal_rpc_member<Irq_context> _dispatcher; Genode::Signal_rpc_member<Irq_context> _dispatcher;
Genode::Irq_session_capability _irq_cap;
Genode::Irq_session_client _irq_client;
static Genode::List<Irq_context> *_list() static Genode::List<Irq_context> *_list()
{ {
@ -72,26 +72,6 @@ class Irq_context : public Genode::List<Irq_context>::Element
return 0; return 0;
} }
/* called by the DDE kit upon IRQ */
static void _dde_handler(void *irq)
{
/*
* Make sure there is only one interrupt handled at a time, since dde_kit
* will use one thread per IRQ
*/
static Genode::Lock handler_lock;
Genode::Lock::Guard guard(handler_lock);
Irq_context *ctx = static_cast<Irq_context *>(irq);
/* set context & submit signal */
_signal->sender().context(ctx->_dispatcher);
_signal->sender().submit();
/* wait for interrupt to get acked at device side */
_irq_sync.lock();
}
/** /**
* Call one IRQ handler * Call one IRQ handler
*/ */
@ -129,8 +109,8 @@ class Irq_context : public Genode::List<Irq_context>::Element
break; break;
} }
/* interrupt should be acked at device now */ /* ack interrupt */
_irq_sync.unlock(); _irq_client.ack_irq();
if (handled) if (handled)
Routine::schedule_all(); Routine::schedule_all();
@ -144,14 +124,18 @@ class Irq_context : public Genode::List<Irq_context>::Element
Irq_context(unsigned int irq) Irq_context(unsigned int irq)
: _irq(irq), : _irq(irq),
_dispatcher(_signal->ep(), *this, &Irq_context::_handle) _dispatcher(_signal->ep(), *this, &Irq_context::_handle),
_irq_cap(platform_irq_activate(_irq)),
_irq_client(_irq_cap)
{ {
/* register at DDE (shared) */ if (!_irq_cap.valid()) {
int ret = dde_kit_interrupt_attach(_irq, 0, 0, _dde_handler, this); PERR("Interrupt %d attach failed", irq);
if (ret) return;
PERR("Interrupt attach return %d for IRQ %u", ret, irq); }
_irq_client.sigh(_dispatcher);
_irq_client.ack_irq();
dde_kit_interrupt_enable(_irq);
_list()->insert(this); _list()->insert(this);
} }