Hi GenodeOS and L4-Hackers community
I'm trying to use DWC_OTG USB Driver for RaspberryPI, using
Fiasco.OC as microkernel with Genode. I have tested the USB driver
using Genode bare metal hardware on RaspberryPI and works fine. I
have reviewed the post published by Simon Arlott about the FIQ and
Bell IRQ:
http://permalink.gmane.org/gmane.linux.kernel.rpi/438
Also I have reviewed the correction implemented by Norman Feske in
the IRQ controller for Genode bare metal hardware:
repos/base-hw/src/core/include/spec/rpi/pic.h
To use Fiasco.OC as microkernel in Genode I have adapted the patch
published in:
http://sourceforge.net/p/genode/mailman/message/33071769/
Based on it, i have tried to use the same idea of Norman Feske,
modifying the Fiasco.OC's IRQ's controller as shown below:
------
kernel/fiasco/src/kern/arm/bsp/bcm2835/mem_layout-arm-bcm2835.cpp
------
index aab5906..4385ebe 100644
@@ -8,5 +8,6 @@ public:
    Pic_phys_base       = 0x2000b200,
    Watchdog_phys_base  = 0x20100000,
    Uart_phys_base      = 0x20201000,
+   Usb_dwc_otg_base    = 0x20980000,
  };
 };
----------
kernel/fiasco/src/kern/arm/bsp/bcm2835/pic-arm-bcm2835.cpp
----------
index 20ed280..13fa623 100644
@@ -7,6 +7,83 @@ IMPLEMENTATION [arm && bcm2835]:
 #include "irq_mgr.h"
 #include "mmio_register_block.h"
 #include "kmem.h"
+#include "warn.h"
+
+class Usb_dwc_otg : Mmio_register_block{
+private:
+Â enum{
+   Core_irq_status_reg  = 0x14,
+   Guid_reg             = 0x3c,
+Â Â Â Host_frame_number_reg = 0x408,
+Â };
+Â bool is_sof() const { return
read<Mword>(Core_irq_status_reg)&0x8; }
+};
+
+PUBLIC
+Usb_dwc_otg::Usb_dwc_otg()
+:
Mmio_register_block(Kmem::mmio_remap(Mem_layout::Usb_dwc_otg_base))
+{
+
+Â write<Mword>(read<Mword>(Guid_reg)&0x3FFFC000,
Guid_reg);
+}
+
+PRIVATE
+static bool
+Usb_dwc_otg::need_trigger_sof(Mword host_frame, Mword
scheduled_frame)
+{
+Â Mword const max_frame = 0x3fff;
+
+Â if (host_frame < scheduled_frame) {
+Â Â Â if (scheduled_frame - host_frame < max_frame / 2)
+Â Â Â Â Â return false;Â /* scheduled frame not reached yet */
+Â Â Â else
+Â Â Â Â Â return true;Â Â /* scheduled frame passed, host frame
wrapped */
+Â } else {
+Â Â Â if (host_frame - scheduled_frame < max_frame / 2)
+Â Â Â Â Â return true;Â Â /* scheduled frame passed */
+Â Â Â else
+Â Â Â Â Â return false;Â /* scheduled frame wrapped, not reached */
+Â }
+}
+
+PUBLIC
+bool
+Usb_dwc_otg::handle_sof()
+{
+Â if (!is_sof())
+Â Â Â return false;
+
+Â static Mword cnt, stat_cnt, filter_cnt, kick_cnt, trigger_cnt;
+
+Â stat_cnt++;
+Â if (stat_cnt == 8000) {
+   WARN("kicked: %d filtered: %d triggered: %d", kick_cnt,
filter_cnt, trigger_cnt);
+Â Â Â stat_cnt = 0;
+Â }
+
+Â cnt++;
+Â if (cnt == 8*20) {
+Â Â Â cnt = 0;
+Â Â Â return false;
+Â }
+
+Â if (read<Mword>(Guid_reg)&0x40000000)
+Â Â Â kick_cnt++;
+
+Â if ((!read<Mword>(Guid_reg)&0x80000000) ||
(read<Mword>(Guid_reg)&0x40000000))
+Â Â Â return false;
+
+Â if
(Usb_dwc_otg::need_trigger_sof(read<Mword>(Host_frame_number_reg)&0x3fff,
read<Mword>(Guid_reg)&0x3fff)) {
+Â Â Â trigger_cnt++;
+Â Â Â return false;
+Â }
+
+Â filter_cnt++;
+
+Â write<Mword>(read<Mword>(Core_irq_status_reg)|0x8,
Core_irq_status_reg);
+
+Â return true;
+}
Â
 class Irq_chip_bcm : public Irq_chip_gen, Mmio_register_block
 {
@@ -29,6 +106,9 @@ public:
  bool is_edge_triggered(Mword) const { return false; }
  void set_cpu(Mword, Cpu_number) {}
  void ack(Mword) { /* ack is empty */ }
+
+private:
+Â Usb_dwc_otg _usb;
 };
Â
 PUBLIC
@@ -97,6 +177,11 @@ Irq_chip_bcm::irq_handler()
        {
          b = 0;
          p = read<Mword>(Irq_pending_1);
+Â Â Â Â Â Â Â Â Â if(p==8){
+Â Â Â Â Â Â Â Â Â Â Â if(_usb.handle_sof()){
+Â Â Â Â Â Â Â Â Â Â Â Â Â return;
+Â Â Â Â Â Â Â Â Â Â Â }
+Â Â Â Â Â Â Â Â Â }
        }
      else if (p & 0x200)
        {
I have tried to test the usb_hid example on Genode using
Fiasco.OC as microkernel
make run/usb_hid
The example compiles fine. When I test it in the emulator QEMU get
the following output
KERNEL: Warning: kicked: 0 filtered: 0Â triggered: 7950
KERNEL: Warning: kicked: 0 filtered: 0Â triggered: 15900
KERNEL: Warning: kicked: 0 filtered: 0Â triggered: 23850
KERNEL: Warning: kicked: 0 filtered: 0Â triggered: 31800
When have tested it on real hardware never get the kernel warning.
It seems that the Kick and Num_valid bits are not
modified by the USB driver.
After that, I have tried to log the USB driver IRQ, setting
#define DEBUG_IRQÂ Â Â Â Â Â Â 1
in the file
repos/dde_linux/src/lib/usb/include/lx_emul.h
Setting this value, the USB driver will log every IRQ handled by the
function _handle() and _handle_one() in the
USB driver. In the Genode bare metal hardware it works fine, but
when tried it with Fiasco.OC, the IRQ handler _handle() and
_handle_one() are never logged.
There's something wrong in my implementation? Someone has tested the
USB driver using Fiasco.OC and Genode together? Why Fiasco.OC's
IRQ's controller is not calling the IRQ's handler defined in the USB
driver?
I'm using Genode commit 63293950261bfb17497433c36a3d62e6e1d813b3,
Fiasco.OC r56 and DWC_OTG commit d08b205cfe01925667f3591117b6d3e1087b4e19.
Best regards
--
Lic. Reinier Millo Sánchez
Centro de Estudios de Informática
Universidad Central "Marta Abreu" de Las Villas
"antes de discutir ... respira;
antes de hablar ... escucha;
antes de escribir ... piensa;
antes de herir ... siente;
antes de rendirte ... intenta;
antes de morir ... vive"