mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-07 03:17:44 +00:00
usb_drv: XHCI support for x86-architectures
USB 3.0 support on x86 (64/32) platforms, as well as pci support for XHCI controllers. Issue #1084
This commit is contained in:
parent
f02e9001e8
commit
5f0843082a
@ -123,6 +123,7 @@ linux-3.9/drivers/usb/host/xhci-ext-caps.h
|
||||
linux-3.9/drivers/usb/host/xhci.h
|
||||
linux-3.9/drivers/usb/host/xhci-hub.c
|
||||
linux-3.9/drivers/usb/host/xhci-mem.c
|
||||
linux-3.9/drivers/usb/host/xhci-pci.c
|
||||
linux-3.9/drivers/usb/host/xhci-plat.c
|
||||
linux-3.9/drivers/usb/host/xhci-ring.c
|
||||
linux-3.9/drivers/usb/storage/alauda.c
|
||||
|
@ -1,5 +1,6 @@
|
||||
SRC_C += usbnet.c asix_devices.c asix_common.c ax88172a.c ax88179_178a.c
|
||||
|
||||
include $(REP_DIR)/lib/mk/xhci.inc
|
||||
include $(REP_DIR)/lib/mk/usb.inc
|
||||
include $(REP_DIR)/lib/mk/arm/usb.inc
|
||||
|
||||
@ -12,7 +13,7 @@ SRC_CC += platform.cc
|
||||
SRC_C += dwc3-exynos.c host.c core.c
|
||||
|
||||
#XHCI
|
||||
SRC_C += xhci-dbg.c xhci-hub.c xhci-mem.c xhci-plat.c xhci-ring.c xhci.c
|
||||
SRC_C += xhci-plat.c
|
||||
|
||||
vpath platform.cc $(LIB_DIR)/arm/platform_arndale
|
||||
vpath %.c $(CONTRIB_DIR)/drivers/usb/dwc3
|
||||
|
21
dde_linux/lib/mk/usb_x86.inc
Normal file
21
dde_linux/lib/mk/usb_x86.inc
Normal file
@ -0,0 +1,21 @@
|
||||
SRC_C += $(addprefix usb/host/,pci-quirks.c uhci-hcd.c ehci-pci.c)
|
||||
|
||||
#
|
||||
# USB netwpork support
|
||||
#
|
||||
SRC_C += usbnet.c ax88179_178a.c
|
||||
|
||||
#XHCI
|
||||
SRC_C += xhci-pci.c
|
||||
|
||||
SRC_CC += pci_driver.cc platform.cc
|
||||
|
||||
include $(REP_DIR)/lib/mk/xhci.inc
|
||||
include $(REP_DIR)/lib/mk/usb.inc
|
||||
|
||||
CC_OPT += -DCONFIG_PCI -DCONFIG_USB_EHCI_PCI=1 -DCONFIG_USB_XHCI_HCD=1
|
||||
|
||||
vpath platform.cc $(LIB_DIR)/x86
|
||||
vpath %.c $(CONTRIB_DIR)/drivers/net/usb
|
||||
|
||||
# vi:set ft=make :
|
@ -1,9 +1,4 @@
|
||||
SRC_C += $(addprefix usb/host/,pci-quirks.c uhci-hcd.c ehci-pci.c)
|
||||
|
||||
include $(REP_DIR)/lib/mk/usb.inc
|
||||
|
||||
CC_OPT += -DCONFIG_PCI -DCONFIG_USB_EHCI_PCI=1 -DCONFIG_USB_XHCI_HCD=0
|
||||
INC_DIR += $(LIB_INC_DIR)/x86_32 $(LIB_INC_DIR)/x86
|
||||
SRC_CC += pci_driver.cc platform.cc
|
||||
|
||||
vpath platform.cc $(LIB_DIR)/x86
|
||||
include $(REP_DIR)/lib/mk/usb_x86.inc
|
||||
|
||||
|
@ -1,9 +1,3 @@
|
||||
SRC_C += $(addprefix usb/host/,pci-quirks.c uhci-hcd.c ehci-pci.c)
|
||||
|
||||
include $(REP_DIR)/lib/mk/usb.inc
|
||||
|
||||
CC_OPT += -DCONFIG_PCI -DCONFIG_USB_EHCI_PCI=1 -DCONFIG_USB_XHCI_HCD=0
|
||||
INC_DIR += $(LIB_INC_DIR)/x86_64 $(LIB_INC_DIR)/x86
|
||||
SRC_CC += pci_driver.cc platform.cc
|
||||
|
||||
vpath platform.cc $(LIB_DIR)/x86
|
||||
include $(REP_DIR)/lib/mk/usb_x86.inc
|
||||
|
6
dde_linux/lib/mk/xhci.inc
Normal file
6
dde_linux/lib/mk/xhci.inc
Normal file
@ -0,0 +1,6 @@
|
||||
#
|
||||
# Generic XHCI files
|
||||
#
|
||||
SRC_C += xhci-dbg.c xhci-hub.c xhci-mem.c xhci-ring.c xhci.c
|
||||
|
||||
# vi:set ft=make :
|
@ -1,20 +0,0 @@
|
||||
diff -r 6978f825431c drivers/usb/host/xhci-plat.c
|
||||
--- a/drivers/usb/host/xhci-plat.c Thu May 16 15:54:34 2013 +0200
|
||||
+++ b/drivers/usb/host/xhci-plat.c Thu May 16 16:41:46 2013 +0200
|
||||
@@ -25,6 +25,16 @@
|
||||
* dev struct in order to setup MSI
|
||||
*/
|
||||
xhci->quirks |= XHCI_BROKEN_MSI;
|
||||
+
|
||||
+#ifdef DWC3_QUIRK
|
||||
+ /*
|
||||
+ * DWC3 controller
|
||||
+ * One will see 'dev_error: ERROR Transfer event TRB DMA ptr not part of
|
||||
+ * current TD' and last message was short (ep_ring->last_td_was_short, in
|
||||
+ * xhci-ring.c
|
||||
+ */
|
||||
+ xhci->quirks |= XHCI_SPURIOUS_SUCCESS;
|
||||
+#endif
|
||||
}
|
||||
|
||||
/* called during probe() after chip reset completes */
|
43
dde_linux/patches/xhci-quirks.patch
Normal file
43
dde_linux/patches/xhci-quirks.patch
Normal file
@ -0,0 +1,43 @@
|
||||
diff -r a103aef8f269 drivers/usb/host/.xhci-pci.c.swp
|
||||
Binary file drivers/usb/host/.xhci-pci.c.swp has changed
|
||||
diff -r a103aef8f269 drivers/usb/host/xhci-pci.c
|
||||
--- a/drivers/usb/host/xhci-pci.c Wed Mar 05 13:54:43 2014 +0100
|
||||
+++ b/drivers/usb/host/xhci-pci.c Wed Mar 05 13:58:50 2014 +0100
|
||||
@@ -34,6 +34,8 @@
|
||||
#define PCI_VENDOR_ID_ETRON 0x1b6f
|
||||
#define PCI_DEVICE_ID_ASROCK_P67 0x7023
|
||||
|
||||
+#define PCI_VENDOR_ID_RENESAS 0x1912
|
||||
+
|
||||
static const char hcd_name[] = "xhci_hcd";
|
||||
|
||||
/* called after powerup, by probe or system-pm "wakeup" */
|
||||
@@ -81,6 +83,10 @@
|
||||
if (pdev->vendor == PCI_VENDOR_ID_NEC)
|
||||
xhci->quirks |= XHCI_NEC_HOST;
|
||||
|
||||
+ /* Quirk for RENESAS USB 3.0 express cards */
|
||||
+ if (pdev->vendor == PCI_VENDOR_ID_RENESAS)
|
||||
+ xhci->quirks |= XHCI_TRUST_TX_LENGTH;
|
||||
+
|
||||
if (pdev->vendor == PCI_VENDOR_ID_AMD && xhci->hci_version == 0x96)
|
||||
xhci->quirks |= XHCI_AMD_0x96_HOST;
|
||||
|
||||
diff -r a103aef8f269 drivers/usb/host/xhci.c
|
||||
--- a/drivers/usb/host/xhci.c Wed Mar 05 13:54:43 2014 +0100
|
||||
+++ b/drivers/usb/host/xhci.c Wed Mar 05 13:58:50 2014 +0100
|
||||
@@ -4683,6 +4683,14 @@
|
||||
|
||||
get_quirks(dev, xhci);
|
||||
|
||||
+
|
||||
+ /* In xhci controllers which follow xhci 1.0 spec gives a spurious
|
||||
+ * success event after a short transfer. This quirk will ignore such
|
||||
+ * spurious event (This is taken from Linux 3.13)
|
||||
+ */
|
||||
+ if (xhci->hci_version > 0x96)
|
||||
+ xhci->quirks |= XHCI_SPURIOUS_SUCCESS;
|
||||
+
|
||||
/* Make sure the HC is halted. */
|
||||
retval = xhci_halt(xhci);
|
||||
if (retval)
|
66
dde_linux/run/usb_hid_panda.run
Normal file
66
dde_linux/run/usb_hid_panda.run
Normal file
@ -0,0 +1,66 @@
|
||||
#
|
||||
# Build
|
||||
#
|
||||
|
||||
set build_components {
|
||||
core init
|
||||
drivers/timer
|
||||
drivers/usb
|
||||
test/input
|
||||
}
|
||||
|
||||
build $build_components
|
||||
|
||||
create_boot_directory
|
||||
|
||||
#
|
||||
# Generate config
|
||||
#
|
||||
|
||||
append config {
|
||||
<config>
|
||||
<parent-provides>
|
||||
<service name="ROM"/>
|
||||
<service name="RAM"/>
|
||||
<service name="IRQ"/>
|
||||
<service name="IO_MEM"/>
|
||||
<service name="IO_PORT"/>
|
||||
<service name="CAP"/>
|
||||
<service name="PD"/>
|
||||
<service name="RM"/>
|
||||
<service name="CPU"/>
|
||||
<service name="LOG"/>
|
||||
<service name="SIGNAL" />
|
||||
</parent-provides>
|
||||
<default-route>
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</default-route>
|
||||
<start name="timer">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
<provides><service name="Timer"/></provides>
|
||||
</start>
|
||||
<start name="usb_drv">
|
||||
<resource name="RAM" quantum="12M"/>
|
||||
<provides><service name="Input"/></provides>
|
||||
<config>
|
||||
<hid/>
|
||||
</config>
|
||||
</start>
|
||||
<start name="test-input">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
</start>
|
||||
</config>}
|
||||
|
||||
install_config $config
|
||||
|
||||
#
|
||||
# Boot modules
|
||||
#
|
||||
|
||||
# generic modules
|
||||
set boot_modules {
|
||||
core init timer usb_drv test-input
|
||||
}
|
||||
|
||||
build_boot_image $boot_modules
|
||||
|
@ -11,7 +11,7 @@
|
||||
# Build
|
||||
#
|
||||
|
||||
build {
|
||||
set build_components {
|
||||
core init
|
||||
drivers/pci drivers/timer drivers/usb
|
||||
test/lwip/http_srv
|
||||
@ -22,6 +22,7 @@ lappend_if [have_spec pci] build_components drivers/pci/device_pd
|
||||
lappend_if [have_spec platform_arndale] build_components drivers/platform
|
||||
lappend_if [have_spec gpio] build_components drivers/gpio
|
||||
|
||||
build $build_components
|
||||
|
||||
create_boot_directory
|
||||
|
||||
@ -56,7 +57,7 @@ set config {
|
||||
<provides>
|
||||
<service name="Nic"/>
|
||||
</provides>
|
||||
<config ehci="yes">
|
||||
<config uhci="no" ehci="yes" xhci="yes">
|
||||
<nic mac="2e:60:90:0c:4e:01" />
|
||||
</config>
|
||||
</start>
|
||||
@ -66,7 +67,7 @@ set config {
|
||||
|
||||
append_if [have_spec acpi] config {
|
||||
<start name="acpi">
|
||||
<resource name="RAM" quantum="5M"/>
|
||||
<resource name="RAM" quantum="10M"/>
|
||||
<binary name="acpi_drv"/>
|
||||
<provides>
|
||||
<service name="PCI"/>
|
||||
@ -122,5 +123,7 @@ lappend_if [have_spec gpio] boot_modules gpio_drv
|
||||
|
||||
build_boot_image $boot_modules
|
||||
|
||||
append qemu_args " -m 256 -nographic"
|
||||
|
||||
run_genode_until forever
|
||||
# vi: set ft=tcl :
|
||||
|
@ -611,6 +611,7 @@ bool in_interrupt(void) { TRACE; return 1; }
|
||||
/*****************
|
||||
** linux/pci.h **
|
||||
*****************/
|
||||
|
||||
int pci_bus_read_config_dword(struct pci_bus *bus, unsigned int devfn, int where, u32 *val) { TRACE; return 0; }
|
||||
int pci_bus_write_config_dword(struct pci_bus *bus, unsigned int devfn, int where, u32 val) { TRACE; return 0; }
|
||||
|
||||
@ -633,6 +634,12 @@ const struct pci_device_id *pci_match_id(const struct pci_device_id *ids,
|
||||
struct pci_dev *dev) { TRACE; return 0; }
|
||||
void *pci_ioremap_bar(struct pci_dev *pdev, int bar);
|
||||
|
||||
int pci_enable_msi(struct pci_dev *pdev) { TRACE; return -1; }
|
||||
void pci_disable_msi(struct pci_dev *pdev) { TRACE; }
|
||||
|
||||
int pci_enable_msix(struct pci_dev *pdev, struct msix_entry *entries, int vec) { TRACE; return -1; }
|
||||
void pci_disable_msix(struct pci_dev *pdev) { TRACE; }
|
||||
|
||||
/**
|
||||
* Omitted PCI functions
|
||||
*/
|
||||
|
@ -645,6 +645,13 @@ int scnprintf(char *buf, size_t size, const char *fmt, ...);
|
||||
struct completion;
|
||||
void complete_and_exit(struct completion *, long);
|
||||
|
||||
|
||||
/*********************
|
||||
** linux/cpumask.h **
|
||||
*********************/
|
||||
|
||||
static inline unsigned num_online_cpus(void) { return 1U; }
|
||||
|
||||
/******************
|
||||
** linux/log2.h **
|
||||
******************/
|
||||
@ -1045,11 +1052,13 @@ typedef void (*work_func_t)(struct work_struct *work);
|
||||
struct work_struct {
|
||||
work_func_t func;
|
||||
struct list_head entry;
|
||||
unsigned pending;
|
||||
};
|
||||
|
||||
struct delayed_work {
|
||||
struct timer_list timer;
|
||||
struct work_struct work;
|
||||
unsigned pending;
|
||||
};
|
||||
|
||||
bool cancel_work_sync(struct work_struct *work);
|
||||
@ -1062,10 +1071,17 @@ bool flush_work_sync(struct work_struct *work);
|
||||
|
||||
|
||||
#define PREPARE_WORK(_work, _func) \
|
||||
do { (_work)->func = (_func); } while (0)
|
||||
do { \
|
||||
(_work)->func = (_func); \
|
||||
(_work)->pending = 0; \
|
||||
} while (0)
|
||||
|
||||
#define PREPARE_DELAYED_WORK(_work, _func) \
|
||||
PREPARE_WORK(&(_work)->work, (_func))
|
||||
do { \
|
||||
PREPARE_WORK(&(_work)->work, (_func)); \
|
||||
(_work)->pending = 0; \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define __INIT_WORK(_work, _func, on_stack) \
|
||||
do { \
|
||||
@ -1080,6 +1096,7 @@ bool flush_work_sync(struct work_struct *work);
|
||||
do { \
|
||||
INIT_WORK(&(_work)->work, (_func)); \
|
||||
init_timer(&(_work)->timer); \
|
||||
(_work)->pending = 0; \
|
||||
} while (0)
|
||||
|
||||
|
||||
@ -2201,12 +2218,9 @@ bool in_interrupt(void);
|
||||
/*
|
||||
* Definitions normally found in pci_regs.h
|
||||
*/
|
||||
//enum { PCI_BASE_ADDRESS_MEM_MASK = ~0x0fUL };
|
||||
//enum { PCI_CAP_ID_AGP = 0x02 };
|
||||
extern struct bus_type pci_bus_type;
|
||||
enum { PCI_ANY_ID = ~0U };
|
||||
enum { DEVICE_COUNT_RESOURCE = 6 };
|
||||
//enum { PCIBIOS_MIN_MEM = 0UL };
|
||||
|
||||
#define PCI_DEVICE_CLASS(dev_class,dev_class_mask) \
|
||||
.class = (dev_class), .class_mask = (dev_class_mask), \
|
||||
@ -2232,6 +2246,21 @@ typedef enum { PCI_D0 = 0 } pci_power_t;
|
||||
#define class device_class
|
||||
#endif /* __cplusplus */
|
||||
|
||||
struct msix_entry
|
||||
{
|
||||
u32 vector;
|
||||
u16 entry;
|
||||
};
|
||||
|
||||
struct pci_dev;
|
||||
|
||||
int pci_enable_msi(struct pci_dev *);
|
||||
void pci_disable_msi(struct pci_dev *);
|
||||
|
||||
int pci_enable_msix(struct pci_dev *, struct msix_entry *, int);
|
||||
void pci_disable_msix(struct pci_dev *);
|
||||
|
||||
|
||||
#include <linux/mod_devicetable.h>
|
||||
|
||||
/*
|
||||
@ -2769,6 +2798,8 @@ int scsi_normalize_sense(const u8 *sense_buffer, int sb_len,
|
||||
const u8 * scsi_sense_desc_find(const u8 * sense_buffer, int sb_len,
|
||||
int desc_type);
|
||||
int scsi_sense_valid(struct scsi_sense_hdr *);
|
||||
int scsi_sense_is_deferred(struct scsi_sense_hdr *);
|
||||
|
||||
|
||||
/*********************
|
||||
** scsi/scsi_tcq.h **
|
||||
@ -3429,6 +3460,7 @@ struct tasklet_struct
|
||||
{
|
||||
void (*func)(unsigned long);
|
||||
unsigned long data;
|
||||
unsigned pending;
|
||||
};
|
||||
|
||||
void tasklet_schedule(struct tasklet_struct *t);
|
||||
|
@ -34,7 +34,7 @@ class Routine : public Genode::List<Routine>::Element
|
||||
{
|
||||
private:
|
||||
|
||||
enum { STACK_SIZE = 0x2000 };
|
||||
enum { STACK_SIZE = 4 * 1024 * sizeof(long) };
|
||||
bool _started; /* true if already started */
|
||||
jmp_buf _env; /* state */
|
||||
int (*_func)(void *); /* function to call*/
|
||||
|
@ -914,7 +914,7 @@ int fls(int x)
|
||||
|
||||
for (int i = 31; i >= 0; i--)
|
||||
if (x & (1 << i))
|
||||
return i;
|
||||
return i + 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -77,6 +77,10 @@ class Work : public Genode::List<Work>::Element
|
||||
template <typename WORK>
|
||||
static void schedule(WORK *work)
|
||||
{
|
||||
if (work->pending)
|
||||
return;
|
||||
|
||||
work->pending = 1;
|
||||
_list()->insert(new (Genode::env()->heap()) Work(work));
|
||||
}
|
||||
|
||||
@ -92,6 +96,7 @@ class Work : public Genode::List<Work>::Element
|
||||
{
|
||||
work_struct *work = static_cast<work_struct *>(w->_work);
|
||||
work->func(work);
|
||||
work->pending = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -99,6 +104,7 @@ class Work : public Genode::List<Work>::Element
|
||||
{
|
||||
delayed_work *work = static_cast<delayed_work *>(w->_work);
|
||||
work->work.func(&(work)->work);
|
||||
work->pending = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -106,6 +112,7 @@ class Work : public Genode::List<Work>::Element
|
||||
{
|
||||
tasklet_struct *tasklet = static_cast<tasklet_struct *>(w->_work);
|
||||
tasklet->func(tasklet->data);
|
||||
tasklet->pending = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -269,8 +276,9 @@ bool queue_delayed_work(struct workqueue_struct *wq,
|
||||
|
||||
void tasklet_init(struct tasklet_struct *t, void (*f)(unsigned long), unsigned long d)
|
||||
{
|
||||
t->func = f;
|
||||
t->data = d;
|
||||
t->func = f;
|
||||
t->data = d;
|
||||
t->pending = 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -120,13 +120,11 @@ class Irq_context : public Genode::List<Irq_context>::Element
|
||||
bool handled = false;
|
||||
|
||||
/* report IRQ to all clients */
|
||||
for (Irq_handler *h = _handler_list.first(); h; h = h->next()) {
|
||||
|
||||
if ((handled = _handle_one(h)))
|
||||
for (Irq_handler *h = _handler_list.first(); h; h = h->next())
|
||||
if ((handled = _handle_one(h))) {
|
||||
dde_kit_log(DEBUG_IRQ, "IRQ: %u ret: %u h: %p dev: %p", _irq, handled, h->handler, h->dev);
|
||||
break;
|
||||
|
||||
dde_kit_log(DEBUG_IRQ, "IRQ: %u ret: %u h: %p dev: %p", _irq, handled, h->handler, h->dev);
|
||||
}
|
||||
}
|
||||
|
||||
/* interrupt should be acked at device now */
|
||||
_irq_sync.unlock();
|
||||
|
@ -15,12 +15,23 @@
|
||||
#include <platform/platform.h>
|
||||
|
||||
|
||||
extern "C" void module_ax88179_178a_driver_init();
|
||||
extern "C" void module_usbnet_init();
|
||||
extern "C" void module_ehci_hcd_init();
|
||||
extern "C" void module_ehci_pci_init();
|
||||
extern "C" void module_uhci_hcd_init();
|
||||
extern "C" void module_xhci_hcd_init();
|
||||
|
||||
void platform_hcd_init(Services *s)
|
||||
{
|
||||
if (s->nic) {
|
||||
module_usbnet_init();
|
||||
module_ax88179_178a_driver_init();
|
||||
}
|
||||
|
||||
if (s->xhci)
|
||||
module_xhci_hcd_init();
|
||||
|
||||
/* ehci_hcd should always be loaded before uhci_hcd and ohci_hcd, not after */
|
||||
if (s->ehci) {
|
||||
module_ehci_hcd_init();
|
||||
|
Loading…
x
Reference in New Issue
Block a user