diff --git a/repos/base/run/platform_drv.inc b/repos/base/run/platform_drv.inc index 2c3c9ccf1..48eea85b4 100644 --- a/repos/base/run/platform_drv.inc +++ b/repos/base/run/platform_drv.inc @@ -30,6 +30,20 @@ proc need_usb_hid { } { } +## +# Return name of the USB driver binary +# +proc usb_host_drv_binary { } { + if {[have_spec arndale]} { return arndale_usb_host_drv } + if {[have_spec panda]} { return panda_usb_host_drv } + if {[have_spec rpi]} { return rpi_usb_host_drv } + if {[have_spec wand_quad]} { return wand_quad_usb_host_drv } + if {[have_spec odroid_x2]} { return odroid_x2_usb_host_drv } + if {[have_spec x86]} { return x86_pc_usb_host_drv } + return no_usb_drv_available +} + + ## # Return name of the NIC driver binary # diff --git a/repos/dde_linux/lib/import/import-usb_host_include.mk b/repos/dde_linux/lib/import/import-usb_host_include.mk new file mode 100644 index 000000000..f9ab34188 --- /dev/null +++ b/repos/dde_linux/lib/import/import-usb_host_include.mk @@ -0,0 +1,33 @@ +USB_CONTRIB_DIR := $(call select_from_ports,dde_linux)/src/drivers/usb_host + +# architecture-dependent includes +ifeq ($(filter-out $(SPECS),x86),) + ARCH_SRC_INC_DIR += $(REP_DIR)/src/include/spec/x86 + ifeq ($(filter-out $(SPECS),32bit),) + ARCH_SRC_INC_DIR += $(REP_DIR)/src/include/spec/x86_32 + endif # 32bit + ifeq ($(filter-out $(SPECS),64bit),) + ARCH_SRC_INC_DIR += $(REP_DIR)/src/include/spec/x86_64 + endif # 64bit +endif # x86 + +ifeq ($(filter-out $(SPECS),arm),) + ARCH_SRC_INC_DIR += $(REP_DIR)/src/include/spec/arm + ifeq ($(filter-out $(SPECS),arm_v6),) + ARCH_SRC_INC_DIR += $(REP_DIR)/src/include/spec/arm_v6 + endif # arm_v6 + ifeq ($(filter-out $(SPECS),arm_v7),) + ARCH_SRC_INC_DIR += $(REP_DIR)/src/include/spec/arm_v7 + endif # arm_v7 +endif # arm + + +# +# The order of include-search directories is important, we need to look into +# 'contrib' before falling back to our custom 'lx_emul.h' header. +# +INC_DIR += $(ARCH_SRC_INC_DIR) +INC_DIR += $(USB_CONTRIB_DIR)/include +INC_DIR += $(USB_CONTRIB_DIR)/include/uapi +INC_DIR += $(USB_CONTRIB_DIR)/drivers/usb/core +INC_DIR += $(LIB_CACHE_DIR)/usb_host_include/include/include/include diff --git a/repos/dde_linux/lib/mk/usb_host_include.mk b/repos/dde_linux/lib/mk/usb_host_include.mk new file mode 100644 index 000000000..5529a1db8 --- /dev/null +++ b/repos/dde_linux/lib/mk/usb_host_include.mk @@ -0,0 +1,37 @@ +ifeq ($(called_from_lib_mk),yes) + +USB_CONTRIB_DIR := $(call select_from_ports,dde_linux)/src/drivers/usb_host +LX_EMUL_H := $(REP_DIR)/src/drivers/usb_host/lx_emul.h + +# +# Determine the header files included by the contrib code. For each +# of these header files we create a symlink to 'lx_emul.h'. +# +SCAN_DIRS := $(addprefix $(USB_CONTRIB_DIR)/include/, asm-generic linux uapi) \ + $(addprefix $(USB_CONTRIB_DIR)/, drivers lib) +GEN_INCLUDES := $(shell grep -rIh "^\# *include .*\/" $(SCAN_DIRS) |\ + sed "s/^\# *include [^<\"]*[<\"]\([^>\"]*\)[>\"].*/\1/" |\ + sort | uniq) +# +# Filter out original Linux headers that exist in the contrib directory +# +NO_GEN_INCLUDES := $(shell cd $(USB_CONTRIB_DIR)/; find include -name "*.h" |\ + sed "s/.\///" | sed "s/.*include\///") +GEN_INCLUDES := $(filter-out $(NO_GEN_INCLUDES),$(GEN_INCLUDES)) + +# +# Put Linux headers in 'GEN_INC' dir, since some include use "../../" paths use +# three level include hierarchy +# +GEN_INC := $(shell pwd)/include/include/include +GEN_INCLUDES := $(addprefix $(GEN_INC)/,$(GEN_INCLUDES)) + +all: $(GEN_INCLUDES) + +$(GEN_INCLUDES): + $(VERBOSE)mkdir -p $(dir $@) + $(VERBOSE)ln -s $(LX_EMUL_H) $@ + +endif + +CC_CXX_WARN_STRICT = diff --git a/repos/dde_linux/patches/usb_host_mem.patch b/repos/dde_linux/patches/usb_host_mem.patch new file mode 100644 index 000000000..a8577e689 --- /dev/null +++ b/repos/dde_linux/patches/usb_host_mem.patch @@ -0,0 +1,493 @@ +diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c +index c821b4b..5accd4d 100644 +--- a/drivers/usb/core/config.c ++++ b/drivers/usb/core/config.c +@@ -706,7 +706,7 @@ static int usb_parse_configuration(struct usb_device *dev, int cfgidx, + } + + len = sizeof(*intfc) + sizeof(struct usb_host_interface) * j; +- config->intf_cache[i] = intfc = kzalloc(len, GFP_KERNEL); ++ config->intf_cache[i] = intfc = kzalloc(len, GFP_LX_DMA); + if (!intfc) + return -ENOMEM; + kref_init(&intfc->ref); +@@ -817,16 +817,16 @@ int usb_get_configuration(struct usb_device *dev) + } + + length = ncfg * sizeof(struct usb_host_config); +- dev->config = kzalloc(length, GFP_KERNEL); ++ dev->config = kzalloc(length, GFP_LX_DMA); + if (!dev->config) + goto err2; + + length = ncfg * sizeof(char *); +- dev->rawdescriptors = kzalloc(length, GFP_KERNEL); ++ dev->rawdescriptors = kzalloc(length, GFP_LX_DMA); + if (!dev->rawdescriptors) + goto err2; + +- desc = kmalloc(USB_DT_CONFIG_SIZE, GFP_KERNEL); ++ desc = kmalloc(USB_DT_CONFIG_SIZE, GFP_LX_DMA); + if (!desc) + goto err2; + +@@ -855,7 +855,7 @@ int usb_get_configuration(struct usb_device *dev) + USB_DT_CONFIG_SIZE); + + /* Now that we know the length, get the whole thing */ +- bigbuffer = kmalloc(length, GFP_KERNEL); ++ bigbuffer = kmalloc(length, GFP_LX_DMA); + if (!bigbuffer) { + result = -ENOMEM; + goto err; +@@ -928,7 +928,7 @@ int usb_get_bos_descriptor(struct usb_device *dev) + __u8 cap_type; + int ret; + +- bos = kzalloc(sizeof(struct usb_bos_descriptor), GFP_KERNEL); ++ bos = kzalloc(sizeof(struct usb_bos_descriptor), GFP_LX_DMA); + if (!bos) + return -ENOMEM; + +@@ -949,12 +949,12 @@ int usb_get_bos_descriptor(struct usb_device *dev) + if (total_len < length) + return -EINVAL; + +- dev->bos = kzalloc(sizeof(struct usb_host_bos), GFP_KERNEL); ++ dev->bos = kzalloc(sizeof(struct usb_host_bos), GFP_LX_DMA); + if (!dev->bos) + return -ENOMEM; + + /* Now let's get the whole BOS descriptor set */ +- buffer = kzalloc(total_len, GFP_KERNEL); ++ buffer = kzalloc(total_len, GFP_LX_DMA); + if (!buffer) { + ret = -ENOMEM; + goto err; +diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c +index fc32391..919c9e9 100644 +--- a/drivers/usb/core/hcd.c ++++ b/drivers/usb/core/hcd.c +@@ -507,7 +507,7 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb) + * USB hub descriptor. + */ + tbuf_size = max_t(u16, sizeof(struct usb_hub_descriptor), wLength); +- tbuf = kzalloc(tbuf_size, GFP_KERNEL); ++ tbuf = kzalloc(tbuf_size, GFP_LX_DMA); + if (!tbuf) { + status = -ENOMEM; + goto err_alloc; +diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c +index c5c1f6c..5bd400f 100644 +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -706,7 +706,7 @@ resubmit: + if (hub->quiescing) + return; + +- status = usb_submit_urb(hub->urb, GFP_ATOMIC); ++ status = usb_submit_urb(hub->urb, GFP_LX_DMA); + if (status != 0 && status != -ENODEV && status != -EPERM) + dev_err(hub->intfdev, "resubmit --> %d\n", status); + } +@@ -1310,20 +1310,20 @@ static int hub_configure(struct usb_hub *hub, + unsigned full_load; + unsigned maxchild; + +- hub->buffer = kmalloc(sizeof(*hub->buffer), GFP_KERNEL); ++ hub->buffer = kmalloc(sizeof(*hub->buffer), GFP_LX_DMA); + if (!hub->buffer) { + ret = -ENOMEM; + goto fail; + } + +- hub->status = kmalloc(sizeof(*hub->status), GFP_KERNEL); ++ hub->status = kmalloc(sizeof(*hub->status), GFP_LX_DMA); + if (!hub->status) { + ret = -ENOMEM; + goto fail; + } + mutex_init(&hub->status_mutex); + +- hub->descriptor = kzalloc(sizeof(*hub->descriptor), GFP_KERNEL); ++ hub->descriptor = kzalloc(sizeof(*hub->descriptor), GFP_LX_DMA); + if (!hub->descriptor) { + ret = -ENOMEM; + goto fail; +@@ -1565,7 +1565,7 @@ static int hub_configure(struct usb_hub *hub, + if (maxp > sizeof(*hub->buffer)) + maxp = sizeof(*hub->buffer); + +- hub->urb = usb_alloc_urb(0, GFP_KERNEL); ++ hub->urb = usb_alloc_urb(0, GFP_LX_DMA); + if (!hub->urb) { + ret = -ENOMEM; + goto fail; +@@ -4713,7 +4713,7 @@ check_highspeed(struct usb_hub *hub, struct usb_device *udev, int port1) + if (udev->quirks & USB_QUIRK_DEVICE_QUALIFIER) + return; + +- qual = kmalloc(sizeof *qual, GFP_KERNEL); ++ qual = kmalloc(sizeof *qual, GFP_LX_DMA); + if (qual == NULL) + return; + +diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c +index b3f98e0..3442858 100644 +--- a/drivers/usb/core/message.c ++++ b/drivers/usb/core/message.c +@@ -237,7 +237,7 @@ int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, + if (!ep || len < 0) + return -EINVAL; + +- urb = usb_alloc_urb(0, GFP_KERNEL); ++ urb = usb_alloc_urb(0, GFP_LX_DMA); + if (!urb) + return -ENOMEM; + +@@ -990,7 +989,7 @@ int usb_get_status(struct usb_device *dev, int recip, int type, int target, + return -EINVAL; + } + +- status = kmalloc(length, GFP_KERNEL); ++ status = kmalloc(length, GFP_LX_DMA); + if (!status) + return -ENOMEM; + +@@ -2084,7 +2083,7 @@ int usb_driver_set_configuration(struct usb_device *udev, int config) + { + struct set_config_request *req; + +- req = kmalloc(sizeof(*req), GFP_KERNEL); ++ req = kmalloc(sizeof(*req), GFP_LX_DMA); + if (!req) + return -ENOMEM; + req->udev = udev; +diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c +index 0a84661..f427b75 100644 +--- a/drivers/usb/host/ehci-hub.c ++++ b/drivers/usb/host/ehci-hub.c +@@ -749,7 +749,7 @@ static struct urb *request_single_step_set_feature_urb( + struct usb_hcd *hcd = bus_to_hcd(udev->bus); + struct usb_host_endpoint *ep; + +- urb = usb_alloc_urb(0, GFP_KERNEL); ++ urb = usb_alloc_urb(0, GFP_LX_DMA); + if (!urb) + return NULL; + +@@ -804,11 +803,11 @@ static int ehset_single_step_set_feature(struct usb_hcd *hcd, int port) + ehci_err(ehci, "No device attached to the RootHub\n"); + return -ENODEV; + } +- buf = kmalloc(USB_DT_DEVICE_SIZE, GFP_KERNEL); ++ buf = kmalloc(USB_DT_DEVICE_SIZE, GFP_LX_DMA); + if (!buf) + return -ENOMEM; + +- dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL); ++ dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_LX_DMA); + if (!dr) { + kfree(buf); + return -ENOMEM; +diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c +index 3276304..8b9e337 100644 +--- a/drivers/usb/host/ehci-q.c ++++ b/drivers/usb/host/ehci-q.c +@@ -1020,7 +1020,7 @@ static struct ehci_qh *qh_append_tds ( + qh = (struct ehci_qh *) *ptr; + if (unlikely (qh == NULL)) { + /* can't sleep here, we have ehci->lock... */ +- qh = qh_make (ehci, urb, GFP_ATOMIC); ++ qh = qh_make (ehci, urb, GFP_LX_DMA); + *ptr = qh; + } + if (likely (qh != NULL)) { +@@ -1172,7 +1172,7 @@ static int submit_single_step_set_feature( + head = &qtd_list; + + /* URBs map to sequences of QTDs: one logical transaction */ +- qtd = ehci_qtd_alloc(ehci, GFP_KERNEL); ++ qtd = ehci_qtd_alloc(ehci, GFP_LX_DMA); + if (unlikely(!qtd)) + return -1; + list_add_tail(&qtd->qtd_list, head); +@@ -1193,7 +1193,7 @@ static int submit_single_step_set_feature( + sizeof(struct usb_ctrlrequest), + QTD_IOC | token | (2 /* "setup" */ << 8), 8); + +- submit_async(ehci, urb, &qtd_list, GFP_ATOMIC); ++ submit_async(ehci, urb, &qtd_list, GFP_LX_DMA); + return 0; /*Return now; we shall come back after 15 seconds*/ + } + +@@ -1221,7 +1221,7 @@ static int submit_single_step_set_feature( + token |= QTD_TOGGLE; /* force DATA1 */ + + qtd_prev = qtd; +- qtd = ehci_qtd_alloc(ehci, GFP_ATOMIC); ++ qtd = ehci_qtd_alloc(ehci, GFP_LX_DMA); + if (unlikely(!qtd)) + goto cleanup; + qtd->urb = urb; +@@ -1231,7 +1231,7 @@ static int submit_single_step_set_feature( + /* Interrupt after STATUS completion */ + qtd_fill(ehci, qtd, 0, 0, token | QTD_IOC, 0); + +- submit_async(ehci, urb, &qtd_list, GFP_KERNEL); ++ submit_async(ehci, urb, &qtd_list, GFP_LX_DMA); + + return 0; + +diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c +index ac7d4ac..1eb1fc7 100644 +--- a/drivers/usb/host/ohci-dbg.c ++++ b/drivers/usb/host/ohci-dbg.c +@@ -683,7 +683,7 @@ static int fill_buffer(struct debug_buffer *buf) + int ret = 0; + + if (!buf->page) +- buf->page = (char *)get_zeroed_page(GFP_KERNEL); ++ buf->page = (char *)get_zeroed_page(GFP_LX_DMA); + + if (!buf->page) { + ret = -ENOMEM; +diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c +index d088c34..2211b20 100644 +--- a/drivers/usb/host/ohci-hcd.c ++++ b/drivers/usb/host/ohci-hcd.c +@@ -506,7 +506,7 @@ static int ohci_init (struct ohci_hcd *ohci) + ohci->prev_frame_no = IO_WATCHDOG_OFF; + + ohci->hcca = dma_alloc_coherent (hcd->self.controller, +- sizeof(*ohci->hcca), &ohci->hcca_dma, GFP_KERNEL); ++ sizeof(*ohci->hcca), &ohci->hcca_dma, GFP_LX_DMA); + if (!ohci->hcca) + return -ENOMEM; + +diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c +index f9c3947..99a1696 100644 +--- a/drivers/usb/host/uhci-hcd.c ++++ b/drivers/usb/host/uhci-hcd.c +@@ -602,7 +602,7 @@ static int uhci_start(struct usb_hcd *hcd) + + uhci->frame = dma_zalloc_coherent(uhci_dev(uhci), + UHCI_NUMFRAMES * sizeof(*uhci->frame), +- &uhci->frame_dma_handle, GFP_KERNEL); ++ &uhci->frame_dma_handle, GFP_LX_DMA); + if (!uhci->frame) { + dev_err(uhci_dev(uhci), + "unable to allocate consistent memory for frame list\n"); +@@ -610,7 +610,7 @@ static int uhci_start(struct usb_hcd *hcd) + } + + uhci->frame_cpu = kcalloc(UHCI_NUMFRAMES, sizeof(*uhci->frame_cpu), +- GFP_KERNEL); ++ GFP_LX_DMA); + if (!uhci->frame_cpu) + goto err_alloc_frame_cpu; + +diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c +index 35fcb82..3a0cff5 100644 +--- a/drivers/usb/host/uhci-q.c ++++ b/drivers/usb/host/uhci-q.c +@@ -108,7 +108,7 @@ static struct uhci_td *uhci_alloc_td(struct uhci_hcd *uhci) + dma_addr_t dma_handle; + struct uhci_td *td; + +- td = dma_pool_alloc(uhci->td_pool, GFP_ATOMIC, &dma_handle); ++ td = dma_pool_alloc(uhci->td_pool, GFP_LX_DMA, &dma_handle); + if (!td) + return NULL; + +@@ -248,7 +248,7 @@ static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci, + dma_addr_t dma_handle; + struct uhci_qh *qh; + +- qh = dma_pool_zalloc(uhci->qh_pool, GFP_ATOMIC, &dma_handle); ++ qh = dma_pool_zalloc(uhci->qh_pool, GFP_LX_DMA, &dma_handle); + if (!qh) + return NULL; + +@@ -724,7 +724,7 @@ static inline struct urb_priv *uhci_alloc_urb_priv(struct uhci_hcd *uhci, + { + struct urb_priv *urbp; + +- urbp = kmem_cache_zalloc(uhci_up_cachep, GFP_ATOMIC); ++ urbp = kmem_cache_zalloc(uhci_up_cachep, GFP_LX_DMA); + if (!urbp) + return NULL; + +diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c +index 72ebbc9..0e815a8 100644 +--- a/drivers/usb/host/xhci-hub.c ++++ b/drivers/usb/host/xhci-hub.c +@@ -404,7 +404,7 @@ static int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend) + if (GET_EP_CTX_STATE(ep_ctx) != EP_STATE_RUNNING) + continue; + +- command = xhci_alloc_command(xhci, false, GFP_NOWAIT); ++ command = xhci_alloc_command(xhci, false, GFP_LX_DMA); + if (!command) { + spin_unlock_irqrestore(&xhci->lock, flags); + ret = -ENOMEM; +diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c +index 332420d..e037aaf 100644 +--- a/drivers/usb/host/xhci-mem.c ++++ b/drivers/usb/host/xhci-mem.c +@@ -2135,7 +2135,7 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports, + rhub->psi_count = XHCI_EXT_PORT_PSIC(temp); + if (rhub->psi_count) { + rhub->psi = kcalloc(rhub->psi_count, sizeof(*rhub->psi), +- GFP_KERNEL); ++ GFP_LX_DMA); + if (!rhub->psi) + rhub->psi_count = 0; + +diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c +index daa94c3..028891a 100644 +--- a/drivers/usb/host/xhci-ring.c ++++ b/drivers/usb/host/xhci-ring.c +@@ -1141,7 +1141,7 @@ static void xhci_handle_cmd_reset_ep(struct xhci_hcd *xhci, int slot_id, + if (xhci->quirks & XHCI_RESET_EP_QUIRK) { + struct xhci_command *command; + +- command = xhci_alloc_command(xhci, false, GFP_ATOMIC); ++ command = xhci_alloc_command(xhci, false, GFP_LX_DMA); + if (!command) + return; + +@@ -1821,7 +1821,7 @@ static void xhci_cleanup_halted_endpoint(struct xhci_hcd *xhci, + { + struct xhci_virt_ep *ep = &xhci->devs[slot_id]->eps[ep_index]; + struct xhci_command *command; +- command = xhci_alloc_command(xhci, false, GFP_ATOMIC); ++ command = xhci_alloc_command(xhci, false, GFP_LX_DMA); + if (!command) + return; + +@@ -3906,7 +3906,7 @@ static int queue_command(struct xhci_hcd *xhci, struct xhci_command *cmd, + reserved_trbs++; + + ret = prepare_ring(xhci, xhci->cmd_ring, EP_STATE_RUNNING, +- reserved_trbs, GFP_ATOMIC); ++ reserved_trbs, GFP_LX_DMA); + if (ret < 0) { + xhci_err(xhci, "ERR: No room for command on command ring\n"); + if (command_must_succeed) +@@ -4040,7 +4040,7 @@ void xhci_queue_new_dequeue_state(struct xhci_hcd *xhci, + } + + /* This function gets called from contexts where it cannot sleep */ +- cmd = xhci_alloc_command(xhci, false, GFP_ATOMIC); ++ cmd = xhci_alloc_command(xhci, false, GFP_LX_DMA); + if (!cmd) + return; + +diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c +index 5d37700..1945abb 100644 +--- a/drivers/usb/host/xhci.c ++++ b/drivers/usb/host/xhci.c +@@ -602,7 +604,7 @@ int xhci_run(struct usb_hcd *hcd) + if (xhci->quirks & XHCI_NEC_HOST) { + struct xhci_command *command; + +- command = xhci_alloc_command(xhci, false, GFP_KERNEL); ++ command = xhci_alloc_command(xhci, false, GFP_LX_DMA); + if (!command) + return -ENOMEM; + +@@ -1244,7 +1246,7 @@ static int xhci_check_maxpacket(struct xhci_hcd *xhci, unsigned int slot_id, + * changes max packet sizes. + */ + +- command = xhci_alloc_command(xhci, true, GFP_KERNEL); ++ command = xhci_alloc_command(xhci, true, GFP_LX_DMA); + if (!command) + return -ENOMEM; + +@@ -1355,7 +1357,7 @@ static int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flag + switch (usb_endpoint_type(&urb->ep->desc)) { + + case USB_ENDPOINT_XFER_CONTROL: +- ret = xhci_queue_ctrl_tx(xhci, GFP_ATOMIC, urb, ++ ret = xhci_queue_ctrl_tx(xhci, GFP_LX_DMA, urb, + slot_id, ep_index); + break; + case USB_ENDPOINT_XFER_BULK: +@@ -1366,18 +1368,18 @@ static int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flag + ret = -EINVAL; + break; + } +- ret = xhci_queue_bulk_tx(xhci, GFP_ATOMIC, urb, ++ ret = xhci_queue_bulk_tx(xhci, GFP_LX_DMA, urb, + slot_id, ep_index); + break; + + + case USB_ENDPOINT_XFER_INT: +- ret = xhci_queue_intr_tx(xhci, GFP_ATOMIC, urb, ++ ret = xhci_queue_intr_tx(xhci, GFP_LX_DMA, urb, + slot_id, ep_index); + break; + + case USB_ENDPOINT_XFER_ISOC: +- ret = xhci_queue_isoc_tx_prepare(xhci, GFP_ATOMIC, urb, ++ ret = xhci_queue_isoc_tx_prepare(xhci, GFP_LX_DMA, urb, + slot_id, ep_index); + } + +@@ -1499,7 +1501,7 @@ static int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) + * the first cancellation to be handled. + */ + if (!(ep->ep_state & EP_STOP_CMD_PENDING)) { +- command = xhci_alloc_command(xhci, false, GFP_ATOMIC); ++ command = xhci_alloc_command(xhci, false, GFP_LX_DMA); + if (!command) { + ret = -ENOMEM; + goto done; +@@ -2684,7 +2686,7 @@ static int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev) + xhci_dbg(xhci, "%s called for udev %p\n", __func__, udev); + virt_dev = xhci->devs[udev->slot_id]; + +- command = xhci_alloc_command(xhci, true, GFP_KERNEL); ++ command = xhci_alloc_command(xhci, true, GFP_LX_DMA); + if (!command) + return -ENOMEM; + +@@ -3560,7 +3562,7 @@ int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id) + u32 state; + int ret = 0; + +- command = xhci_alloc_command(xhci, false, GFP_KERNEL); ++ command = xhci_alloc_command(xhci, false, GFP_LX_DMA); + if (!command) + return -ENOMEM; + +@@ -3622,7 +3624,7 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev) + int ret, slot_id; + struct xhci_command *command; + +- command = xhci_alloc_command(xhci, true, GFP_KERNEL); ++ command = xhci_alloc_command(xhci, true, GFP_LX_DMA); + if (!command) + return 0; + +@@ -3755,7 +3757,7 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev, + } + } + +- command = xhci_alloc_command(xhci, true, GFP_KERNEL); ++ command = xhci_alloc_command(xhci, true, GFP_LX_DMA); + if (!command) { + ret = -ENOMEM; + goto out; +@@ -4688,7 +4690,7 @@ static int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev, + + spin_lock_irqsave(&xhci->lock, flags); + if (hdev->speed == USB_SPEED_HIGH && +- xhci_alloc_tt_info(xhci, vdev, hdev, tt, GFP_ATOMIC)) { ++ xhci_alloc_tt_info(xhci, vdev, hdev, tt, GFP_LX_DMA)) { + xhci_dbg(xhci, "Could not allocate xHCI TT structure.\n"); + xhci_free_command(xhci, config_cmd); + spin_unlock_irqrestore(&xhci->lock, flags); diff --git a/repos/dde_linux/patches/usb_host_omap.patch b/repos/dde_linux/patches/usb_host_omap.patch new file mode 100644 index 000000000..bb58ed7c2 --- /dev/null +++ b/repos/dde_linux/patches/usb_host_omap.patch @@ -0,0 +1,12 @@ +diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c +index 8d8bafc..3c3f71c 100644 +--- a/drivers/usb/host/ehci-omap.c ++++ b/drivers/usb/host/ehci-omap.c +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + #include + #include + diff --git a/repos/dde_linux/ports/dde_linux.hash b/repos/dde_linux/ports/dde_linux.hash index 01c53b32d..d5216bd5e 100644 --- a/repos/dde_linux/ports/dde_linux.hash +++ b/repos/dde_linux/ports/dde_linux.hash @@ -1 +1 @@ -4a6dd8a8cd9919910a4988a1218b2de29016349a +d0b8fe75d35d994df3bc98161d5d7558513a5d4a diff --git a/repos/dde_linux/ports/dde_linux.port b/repos/dde_linux/ports/dde_linux.port index c59643fd6..5b9f04efe 100644 --- a/repos/dde_linux/ports/dde_linux.port +++ b/repos/dde_linux/ports/dde_linux.port @@ -2,21 +2,25 @@ LICENSE := GPLv2 VERSION := 2 DOWNLOADS := dwc_otg.git usb.archive intel_fb.archive lxip.archive \ wifi.archive fec.archive libnl.archive wpa_supplicant.git \ - fw.archive + fw.archive usb_host.archive dwc_otg_host.git + +# +# Tools +# +$(call check_tool,flex) +$(call check_tool,bison) + +FLEX = flex +YACC = bison # # The git checkout checks for the existence of SRC_DIR, which is created by the # Linux extraction, therefore make sure to checkout the GIT sources first. # usb.archive: dwc_otg.git +usb_host.archive: dwc_otg_host.git -# -# The git checkout checks for the existence of SRC_DIR, which is created by the -# Linux extraction, therefore make sure to checkout the GIT sources first. -# -usb.archive: dwc_otg.git - # # USB # @@ -28,6 +32,17 @@ DIR(usb) := $(SRC_DIR_USB) TAR_OPT(usb) := --strip-components=1 --files-from - < <(sed 's/-x.x.x/-$(VERSION_USB)/g' $(REP_DIR)/usb.list) HASH_INPUT += $(REP_DIR)/usb.list +# +# USB host controller +# +SRC_DIR_USB_HOST := src/drivers/usb_host +VERSION_USB_HOST := 4.16.3 +URL(usb_host) := https://www.kernel.org/pub/linux/kernel/v4.x/linux-$(VERSION_USB_HOST).tar.xz +SHA(usb_host) := 0d6971a81da97e38b974c5eba31a74803bfe41aabc46d406c3acda56306c81a3 +DIR(usb_host) := $(SRC_DIR_USB_HOST) +TAR_OPT(usb_host) := --strip-components=1 --files-from - < <(sed 's/-x.x.x/-$(VERSION_USB_HOST)/g' $(REP_DIR)/usb_host.list) +HASH_INPUT += $(REP_DIR)/usb_host.list + # # Raspberry Pi USB controller # @@ -35,6 +50,10 @@ URL(dwc_otg) := https://github.com/ssumpf/dwc_otg.git REV(dwc_otg) := r3 DIR(dwc_otg) := $(SRC_DIR_USB)/drivers/usb/host/dwc_otg +URL(dwc_otg_host) := https://github.com/skalk/dwc_otg.git +REV(dwc_otg_host) := r4 +DIR(dwc_otg_host) := $(SRC_DIR_USB_HOST)/drivers/usb/host + # # Intel framebuffer driver @@ -112,6 +131,7 @@ PATCHES += $(addprefix patches/,$(notdir $(wildcard $(REP_DIR)/patches/libnl*.pa PATCHES += $(addprefix patches/,$(notdir $(wildcard $(REP_DIR)/patches/wifi*.patch))) PATCHES += $(addprefix patches/,$(notdir $(wildcard $(REP_DIR)/patches/lxip*.patch))) PATCHES += $(addprefix patches/,$(notdir $(wildcard $(REP_DIR)/patches/intel*.patch))) +PATCHES += $(addprefix patches/,$(notdir $(wildcard $(REP_DIR)/patches/usb_host*.patch))) PATCHES += $(addprefix patches/,$(notdir $(wildcard $(REP_DIR)/patches/usb*.patch))) PATCHES += $(addprefix patches/,$(notdir $(wildcard $(REP_DIR)/patches/intel*.patch))) PATCHES += $(addprefix patches/,$(notdir $(wildcard $(REP_DIR)/patches/fec_*.patch))) @@ -147,6 +167,11 @@ PATCH_OPT(patches/usb_usbnet.patch) := $(USB_OPT) PATCH_OPT(patches/usb_rndis.patch) := $(USB_OPT) PATCH_OPT(patches/usb_tv64.patch) := $(USB_OPT) +# USB HOST +USB_HOST_OPT = -p1 -d$(SRC_DIR_USB_HOST) +PATCH_OPT(patches/usb_host_mem.patch) := $(USB_HOST_OPT) +PATCH_OPT(patches/usb_host_omap.patch) := $(USB_HOST_OPT) + # INTEL FB PATCH_OPT(patches/intel_fb_backlight.patch) := -p1 -d$(SRC_DIR_INTEL_FB) PATCH_OPT(patches/intel_fb_drm.patch) := -p1 -d$(SRC_DIR_INTEL_FB) diff --git a/repos/dde_linux/src/drivers/usb_host/README b/repos/dde_linux/src/drivers/usb_host/README new file mode 100644 index 000000000..ef2f4ddcb --- /dev/null +++ b/repos/dde_linux/src/drivers/usb_host/README @@ -0,0 +1,66 @@ +USB host controller driver +########################## + +Allows access to USB devices via the 'Usb' session interface. + +Configuration snippet: + +! +! +! +! +! +! +! + +The optional 'devices' report lists the connected devices and gets updated +when devices are added or removed. + +Example report: + +! +! +! +! + +For every device a unique identifier is generated that is used to access the +USB device. Only devices that have a valid policy configured at the USB driver +can be accessed by a client. The following configuration allows 'comp1' to +access the device 'usb-1-6': + +! +! +! +! +! +! +! +! +! +! + +In addition to the mandatory 'label' attribute the policy node also +contains optional attribute tuples of which at least one has to be present. +The 'vendor_id' and 'product_id' tuple selects a device regardless of its +location on the USB bus and is mostly used in static configurations. The +'bus' and 'dev' tuple selects a specific device via its bus locations and +device address. It is mostly used in dynamic configurations because the device +address is not fixed and may change every time the same device is plugged in. +If the class attribute is defined only, the usb host controller driver allows +access to all devives of that class. In that case the actual device is chosen +by the last label given when a session gets opened. + + +BIOS Handoff +~~~~~~~~~~~~ + +Per default the USB driver performs a hand off of the USB controller from the +BIOS, since it still may access the controller when booting, for example, from +a USB device. The BIOS hand off induces the execution of BIOS/SMM USB driver +code and potentially DMA operations. Unfortunately, some ACPI tables report +wrong RMRR information, which implicates IOMMU faults on illegal DMA +operations and consequently the hand off may fail after noticeably long +timeouts. Therefore, the hand off can be disabled in the USB driver +configuration like follows. + +! diff --git a/repos/dde_linux/src/drivers/usb_host/dummies.c b/repos/dde_linux/src/drivers/usb_host/dummies.c new file mode 100644 index 000000000..8c448b3cb --- /dev/null +++ b/repos/dde_linux/src/drivers/usb_host/dummies.c @@ -0,0 +1,1229 @@ +/* + * \brief Dummy functions + * \author Norman Feske + * \author Sebastian sumpf + * \date 2011-01-29 + */ + +/* + * Copyright (C) 2011-2017 Genode Labs GmbH + * Copyright (C) 2014 Ksys Labs LLC + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +/* Linux kernel API */ +#include + +#define SKIP_VERBOSE 0 + +#if DEBUG_TRACE +#define TRACE lx_printf("\033[32m%s\033[0m called from %p, not implemented\n", __PRETTY_FUNCTION__, __builtin_return_address(0)) +#else +#define TRACE +#endif +#if SKIP_VERBOSE +#define SKIP lx_printf("\033[34m%s\033[0m: skipped\n", __PRETTY_FUNCTION__) +#else +#define SKIP +#endif + +#define TRACE_AND_STOP \ + do { \ + lx_printf("%s not implemented\n", __func__); \ + BUG(); \ + } while (0) + + +/****************** + ** linux/slab.h ** + ******************/ + +void *kmalloc_array(size_t n, size_t size, gfp_t flags) { TRACE; return (void *)0xdeadbeaf; } + + +/******************** + ** linux/kernel.h ** + ********************/ + +void might_sleep() { SKIP; } +char *kasprintf(gfp_t gfp, const char *fmt, ...) { TRACE; return NULL; } +int kstrtouint(const char *s, unsigned int base, unsigned int *res) { TRACE; return 0; } +int kstrtoul(const char *s, unsigned int base, unsigned long *res) { TRACE; return 0; } +int kstrtou8(const char *s, unsigned int base, u8 *x) { TRACE; return 1; } +int sprintf(char *buf, const char *fmt, ...) { TRACE; return 0; } +int sscanf(const char *b, const char *s, ...) { TRACE; return 0; } +int scnprintf(char *buf, size_t size, const char *fmt, ...); +int strict_strtoul(const char *s, unsigned int base, unsigned long *res) { TRACE; return 0; } +long simple_strtoul(const char *cp, char **endp, unsigned int base) { TRACE; return 0; } + + +/****************** + ** linux/log2.h ** + ******************/ + +int roundup_pow_of_two(u32 n) { TRACE; return 0; } + + +/******************** + ** linux/printk.h ** + ********************/ + +void print_hex_dump(const char *level, const char *prefix_str, + int prefix_type, int rowsize, int groupsize, + const void *buf, size_t len, bool ascii) { TRACE; } +bool printk_ratelimit() { TRACE; return 0; } +bool printk_timed_ratelimit(unsigned long *caller_jiffies, + unsigned int interval_msec) { TRACE; return false; } + + +/********************************** + ** linux/bitops.h, asm/bitops.h ** + **********************************/ + +int ffs(int x) { TRACE; return 0; } + + +/******************** + ** linux/string.h ** + ********************/ + +int memcmp(const void *dst, const void *src, size_t s) { TRACE; return 0; } +char *strcat(char *dest, const char *src) { TRACE; return 0; } +int strncmp(const char *cs, const char *ct, size_t count) { TRACE; return 0; } +char *strncpy(char *dst, const char *src, size_t s) { TRACE; return NULL; } +char *strchr(const char *s, int n) { TRACE; return NULL; } +char *strrchr(const char *s, int n) { TRACE; return NULL; } +char *strsep(char **s,const char *d) { TRACE; return NULL; } +char *kstrdup(const char *s, gfp_t gfp) { TRACE; return 0; } +char *strstr(const char *h, const char *n) { TRACE; return 0; } + + +/******************* + ** linux/ctype.h ** + *******************/ + +int isprint(int v) { TRACE; return 0; } + + +/********************** + ** linux/spinlock.h ** + **********************/ + +void spin_lock(spinlock_t *lock) { SKIP; } +void spin_lock_nested(spinlock_t *lock, int subclass) { TRACE; } +void spin_unlock(spinlock_t *lock) { SKIP; } +void spin_lock_init(spinlock_t *lock) { SKIP; } +void spin_lock_irqsave(spinlock_t *lock, unsigned long flags) { SKIP; } +void spin_lock_irqrestore(spinlock_t *lock, unsigned long flags) { SKIP; } +void spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags) { SKIP; } +void spin_lock_irq(spinlock_t *lock) { SKIP; } +void spin_unlock_irq(spinlock_t *lock) { SKIP; } +void assert_spin_locked(spinlock_t *lock) { TRACE;} + + +/******************* + ** linux/rwsem.h ** + *******************/ + +void down_read(struct rw_semaphore *sem) { SKIP; } +void up_read(struct rw_semaphore *sem) { SKIP; } +void down_write(struct rw_semaphore *sem) { SKIP; } +void up_write(struct rw_semaphore *sem) { SKIP; } + + +/********************* + ** linux/lockdep.h ** + *********************/ + +bool lockdep_is_held(void *l) { TRACE; return 1; } + + +/******************** + ** linux/random.h ** + ********************/ + +void add_device_randomness(const void *buf, unsigned int size) { TRACE; } + + +/******************* + ** linux/ktime.h ** + *******************/ + +#define KTIME_RET ({TRACE; ktime_t t = { 0 }; return t;}) + +ktime_t ktime_add_ns(const ktime_t kt, u64 nsec) { KTIME_RET; } +ktime_t ktime_get_monotonic_offset(void) { KTIME_RET; } +ktime_t ktime_sub(const ktime_t lhs, const ktime_t rhs) { KTIME_RET; } +ktime_t ktime_get_real(void) { TRACE; ktime_t ret; return ret; } +ktime_t ktime_get_boottime(void) { TRACE; KTIME_RET; } + +s64 ktime_us_delta(const ktime_t later, const ktime_t earlier) { TRACE; return 0; }; + + +/******************* + ** linux/timer.h ** + *******************/ + +unsigned long round_jiffies(unsigned long j) { TRACE; return 1; } +void set_timer_slack(struct timer_list *time, int slack_hz) { TRACE; } + + +/*********************** + ** linux/workquque.h ** + ***********************/ + +void destroy_workqueue(struct workqueue_struct *wq) { TRACE; } + +bool flush_work(struct work_struct *work) { TRACE; return 0; } +bool flush_work_sync(struct work_struct *work) { TRACE; return 0; } + + +/****************** + ** linux/time.h ** + ******************/ + +struct timespec current_kernel_time(void) +{ + struct timespec t = { 0, 0 }; + return t; +} + +void do_gettimeofday(struct timeval *tv) { TRACE; } + + +/******************* + ** linux/sched.h ** + *******************/ + +void __set_current_state(int state) { TRACE; } +void schedule(void) { TRACE; } +void yield(void) { TRACE; } +void cpu_relax(void) { SKIP; } + +struct task_struct *current; + + +/********************* + ** linux/kthread.h ** + *********************/ + +int kthread_should_stop(void) { SKIP; return 0; } +int kthread_stop(struct task_struct *k) { TRACE; return 0; } + + +/********************** + ** linux/notifier.h ** + **********************/ + +int blocking_notifier_chain_unregister(struct blocking_notifier_head *nh, + struct notifier_block *nb) { TRACE; return 0; } +int atomic_notifier_chain_register(struct atomic_notifier_head *nh, + struct notifier_block *nb) { TRACE; return 0; } +int atomic_notifier_chain_unregister(struct atomic_notifier_head *nh, + struct notifier_block *nb) { TRACE; return 0; } + + + +/********************* + ** linux/kobject.h ** + *********************/ + +int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...) { TRACE; return 0; } +char *kobject_name(const struct kobject *kobj) { TRACE; return 0; } +char *kobject_get_path(struct kobject *kobj, gfp_t gfp_mask) { TRACE; return 0; } + + +/******************* + ** linux/sysfs.h ** + *******************/ + +int sysfs_create_group(struct kobject *kobj, + const struct attribute_group *grp) { TRACE; return 0; } +void sysfs_remove_group(struct kobject *kobj, + const struct attribute_group *grp) { TRACE; } +int sysfs_create_link(struct kobject *kobj, struct kobject *target, + const char *name) { TRACE; return 0; } +void sysfs_remove_link(struct kobject *kobj, const char *name) { TRACE; } + +int sysfs_create_files(struct kobject *kobj, const struct attribute **attr) { TRACE; return 1; } + +ssize_t simple_read_from_buffer(void __user *to, size_t count, + loff_t *ppos, const void *from, size_t available) { TRACE; return 0; } + +/************************ + ** linux/pm_runtime.h ** + ************************/ + +bool pm_runtime_active(struct device *dev) { SKIP; return true; } +int pm_runtime_set_active(struct device *dev) { SKIP; return 0; } +void pm_suspend_ignore_children(struct device *dev, bool enable) { SKIP; } +void pm_runtime_enable(struct device *dev) { SKIP; } +void pm_runtime_disable(struct device *dev) { SKIP; } +void pm_runtime_allow(struct device *dev) { SKIP; } +void pm_runtime_forbid(struct device *dev) { SKIP; } +void pm_runtime_set_suspended(struct device *dev) { SKIP; } +void pm_runtime_get_noresume(struct device *dev) { SKIP; } +void pm_runtime_put_noidle(struct device *dev) { SKIP; } +void pm_runtime_use_autosuspend(struct device *dev) { SKIP; } +int pm_runtime_put_sync_autosuspend(struct device *dev) { SKIP; return 0; } +void pm_runtime_no_callbacks(struct device *dev) { SKIP; } +void pm_runtime_set_autosuspend_delay(struct device *dev, int delay) { SKIP; } +int pm_runtime_get_sync(struct device *dev) { SKIP; return 0; } +int pm_runtime_put_sync(struct device *dev) { SKIP; return 0; } +int pm_runtime_put(struct device *dev) { SKIP; return 0; } +int pm_runtime_barrier(struct device *dev) { SKIP; return 0; } + + +/*********************** + ** linux/pm_wakeup.h ** + ***********************/ + +int device_init_wakeup(struct device *dev, bool val) { TRACE; return 0; } +int device_wakeup_enable(struct device *dev) { TRACE; return 0; } +bool device_may_wakeup(struct device *dev) { TRACE; return 1; } +int device_set_wakeup_enable(struct device *dev, bool enable) { TRACE; return 0; } +bool device_can_wakeup(struct device *dev) { TRACE; return 0; } + + +/******************** + ** linux/pm_qos.h ** + ********************/ + +int dev_pm_qos_expose_flags(struct device *dev, s32 value) { TRACE; return 0; } +int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req, + enum dev_pm_qos_req_type type, s32 value) { TRACE; return 0; } +int dev_pm_qos_remove_request(struct dev_pm_qos_request *req) { TRACE; return 0; } + + +/******************** + ** linux/device.h ** + ********************/ + +int dev_set_name(struct device *dev, const char *name, ...) { TRACE; return 0; } +int dev_to_node(struct device *dev) { TRACE; return 0; } +void set_dev_node(struct device *dev, int node) { TRACE; } + +struct device *device_create(struct class *cls, struct device *parent, + dev_t devt, void *drvdata, + const char *fmt, ...) { TRACE; return NULL; } +void device_destroy(struct class *cls, dev_t devt) { TRACE; } +void device_lock(struct device *dev) { TRACE; } +int device_trylock(struct device *dev) { TRACE; return 0; } +void device_unlock(struct device *dev) { TRACE; } +void device_initialize(struct device *dev) { TRACE; } +int device_attach(struct device *dev) { TRACE; return 0; } +int device_bind_driver(struct device *dev) { TRACE; return 0; } +void device_enable_async_suspend(struct device *dev) { TRACE; } +void device_set_wakeup_capable(struct device *dev, bool capable) { TRACE; } +int device_create_file(struct device *device, + const struct device_attribute *entry) { TRACE; return 0; } +void device_remove_file(struct device *dev, + const struct device_attribute *attr) { TRACE; } +int device_for_each_child(struct device *dev, void *data, + int (*fn)(struct device *dev, void *data)) { TRACE; return 0; } + +void driver_unregister(struct device_driver *drv) { TRACE; } +int driver_attach(struct device_driver *drv) { TRACE; return 0; } +int driver_create_file(struct device_driver *driver, + const struct driver_attribute *attr) { TRACE; return 0; } +void driver_remove_file(struct device_driver *driver, + const struct driver_attribute *attr) { TRACE; } + +struct device_driver *get_driver(struct device_driver *drv) { TRACE; return NULL; } +void put_driver(struct device_driver *drv) { TRACE; } + +struct device *bus_find_device(struct bus_type *bus, struct device *start, + void *data, + int (*match)(struct device *dev, void *data)) { TRACE; return NULL; } +int bus_register(struct bus_type *bus) { TRACE; return 0; } +void bus_unregister(struct bus_type *bus) { TRACE; } +int bus_register_notifier(struct bus_type *bus, + struct notifier_block *nb) { TRACE; return 0; } +int bus_unregister_notifier(struct bus_type *bus, + struct notifier_block *nb) { TRACE; return 0; } +int bus_for_each_dev(struct bus_type *bus, struct device *start, void *data, + int (*fn)(struct device *dev, void *data)) { TRACE; return 0; } + +struct class *__class_create(struct module *owner, + const char *name, + struct lock_class_key *key) { TRACE; return NULL; } +int class_register(struct class *cls) { TRACE; return 0; } +void class_unregister(struct class *cls) { TRACE; } +void class_destroy(struct class *cls) { TRACE; } + +void devres_add(struct device *dev, void *res) { TRACE; } +void devres_free(void *res) { TRACE; } + +void devm_kfree(struct device *dev, void *p) { TRACE; } + + +/***************************** + ** linux/platform_device.h ** + *****************************/ + +int platform_device_del(struct platform_device *pdev) { TRACE; return 0; } +int platform_device_put(struct platform_device *pdev) { TRACE; return 0; } +void platform_device_unregister(struct platform_device *pdev) { TRACE; } + + +/******************** + ** linux/dcache.h ** + ********************/ + +void d_instantiate(struct dentry *dentry, struct inode *i) { TRACE; } +int d_unhashed(struct dentry *dentry) { TRACE; return 0; } +void d_delete(struct dentry *d) { TRACE; } +struct dentry *d_alloc_root(struct inode *i) { TRACE; return NULL; } +struct dentry *dget(struct dentry *dentry) { TRACE; return NULL; } +void dput(struct dentry *dentry) { TRACE; } + +void dont_mount(struct dentry *dentry) { TRACE; } + + +/****************** + ** linux/poll.h ** + ******************/ + +void poll_wait(struct file *f, wait_queue_head_t *w, poll_table *p) { TRACE; } + + +/******************** + ** linux/statfs.h ** + ********************/ + +loff_t default_llseek(struct file *file, loff_t offset, int origin) { TRACE; return 0; } + + +/**************** + ** linux/fs.h ** + ****************/ + +unsigned iminor(const struct inode *inode) { TRACE; return 0; } +unsigned imajor(const struct inode *inode) { TRACE; return 0; } + +int register_chrdev_region(dev_t d, unsigned v, const char *s) { TRACE; return 0; } +void unregister_chrdev_region(dev_t d, unsigned v) { TRACE; } +void fops_put(struct file_operations const *fops) { TRACE; } +loff_t noop_llseek(struct file *file, loff_t offset, int origin) { TRACE; return 0; } +int register_chrdev(unsigned int major, const char *name, + const struct file_operations *fops) { TRACE; return 0; } +void unregister_chrdev(unsigned int major, const char *name) { TRACE; } +unsigned int get_next_ino(void) { TRACE; return 0; } +void init_special_inode(struct inode *i, umode_t m, dev_t d) { TRACE; } +int generic_delete_inode(struct inode *inode) { TRACE; return 0; } +void drop_nlink(struct inode *inode) { TRACE; } +void inc_nlink(struct inode *inode) { TRACE; } +void dentry_unhash(struct dentry *dentry) { TRACE; } +void iput(struct inode *i) { TRACE; } +int nonseekable_open(struct inode *inode, struct file *filp) { TRACE; return 0; } +const struct file_operations simple_dir_operations; + +struct inode *file_inode(struct file *f) +{ + TRACE; + static struct inode _i; + return &_i; +} + +/******************* + ** linux/namei.h ** + *******************/ + +struct dentry *lookup_one_len(const char *c, struct dentry *e, int v) { TRACE; return NULL; } + + +/********************** + ** linux/seq_file.h ** + **********************/ + +int seq_printf(struct seq_file *f, const char *fmt, ...) { TRACE; return 0; } +int seq_putc(struct seq_file *f, char c) { TRACE; return 0;} + + +/***************** + ** linux/gfp.h ** + *****************/ + +unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order) { TRACE; return 0; } +void __free_pages(struct page *p, unsigned int order) { TRACE; } +void free_pages(unsigned long addr, unsigned int order) { TRACE; } + + +/********************* + ** linux/proc_fs.h ** + *********************/ + +struct proc_dir_entry *proc_mkdir(const char *s,struct proc_dir_entry *e) { TRACE; return NULL; } +void remove_proc_entry(const char *name, struct proc_dir_entry *parent) { TRACE; } + + +/******************** + * linux/debugfs.h ** + ********************/ + +struct dentry *debugfs_create_dir(const char *name, struct dentry *parent) { TRACE; return (struct dentry *)1; } +struct dentry *debugfs_create_file(const char *name, mode_t mode, + struct dentry *parent, void *data, + const struct file_operations *fops) { TRACE; return (struct dentry *)1; } +void debugfs_remove(struct dentry *dentry) { TRACE; } + + +/************************ + ** linux/page-flags.h ** + ************************/ + +bool is_highmem(void *ptr) { TRACE; return 0; } + + +/**************** + ** linux/mm.h ** + ****************/ + +struct zone *page_zone(const struct page *page) { TRACE; return NULL; } +int is_vmalloc_addr(const void *x) { TRACE; return 0; } +void kvfree(const void *addr) { TRACE; } + + +/********************** + ** linux/highmem.h ** + **********************/ + +void *kmap(struct page *page) { TRACE; return 0; } +void kunmap(struct page *page) { TRACE; } + + +/********************** + ** asm-generic/io.h ** + **********************/ + +void iounmap(volatile void *addr) { TRACE; } +void native_io_delay(void) { TRACE; } + + +/******************** + ** linux/ioport.h ** + ********************/ + +void release_region(resource_size_t start, resource_size_t n) { TRACE; } +void release_mem_region(resource_size_t start, resource_size_t n) { TRACE; } + +/** + * SKIP + */ + +/* implemented in Pci_driver */ +struct resource *request_region(resource_size_t start, resource_size_t n, + const char *name) { SKIP; return (struct resource *)1; } +/* implemented in Pci_driver */ +struct resource *request_mem_region(resource_size_t start, resource_size_t n, + const char *name) { SKIP; return (struct resource *)1; } + +/*********************** + ** linux/interrupt.h ** + ***********************/ + +void local_irq_enable(void) { TRACE; } +void local_irq_disable(void) { TRACE; } +void free_irq(unsigned int i, void *p) { TRACE; } + + +/********************* + ** linux/hardirq.h ** + *********************/ + +void synchronize_irq(unsigned int irq) { TRACE; } +bool in_interrupt(void) { TRACE; return 1; } + + +/***************** + ** linux/pci.h ** + *****************/ + + +void *pci_get_drvdata(struct pci_dev *pdev) { TRACE; return NULL; } +struct pci_dev *pci_get_device(unsigned int vendor, unsigned int device, + struct pci_dev *from) { TRACE; return NULL; } + + +void pci_disable_device(struct pci_dev *dev) { TRACE; } +int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask) { TRACE; return 0; } + +void pci_unregister_driver(struct pci_driver *drv) { TRACE; } + +bool pci_dev_run_wake(struct pci_dev *dev) { TRACE; return 0; } +int pci_set_mwi(struct pci_dev *dev) { TRACE; return 0; } +int pci_find_capability(struct pci_dev *dev, int cap) { TRACE; return 0; } +struct pci_dev *pci_get_slot(struct pci_bus *bus, unsigned int devfn) { TRACE; return NULL; } +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; } + +void pci_disable_msix(struct pci_dev *pdev) { TRACE; } + + +int pci_set_power_state(struct pci_dev *dev, pci_power_t state) { TRACE; return 0; } + + +/** + * Omitted PCI functions + */ +/* scans resources, this is already implemented in 'pci_driver.cc' */ +int pci_enable_device(struct pci_dev *dev) { SKIP; return 0; } + +/* implemented in Pci_driver::_setup_pci_device */ +void pci_set_master(struct pci_dev *dev) { SKIP; } + +/********************** + ** linux/irqflags.h ** + **********************/ + +unsigned long local_irq_save(unsigned long flags) { SKIP; return 0; } +unsigned long local_irq_restore(unsigned long flags) { SKIP; return 0; } +unsigned smp_processor_id() { return 0; } + +/************************* + ** linux/scatterlist.h ** + *************************/ + +void sg_init_table(struct scatterlist *sg, unsigned int nents) { TRACE; } +void sg_set_buf(struct scatterlist *sg, const void *buf, unsigned int buflen) { TRACE; } +void sg_set_page(struct scatterlist *sg, struct page *page, + unsigned int len, unsigned int offset) { TRACE; } +int sg_nents(struct scatterlist *sg) { TRACE; return 0; } + +void sg_miter_start(struct sg_mapping_iter *miter, struct scatterlist *sgl, + unsigned int nents, unsigned int flags) { TRACE; } +bool sg_miter_skip(struct sg_mapping_iter *miter, off_t offset) { TRACE; return false;} +bool sg_miter_next(struct sg_mapping_iter *miter) { TRACE; return false; } +void sg_miter_stop(struct sg_mapping_iter *miter) { TRACE; } + + +/************************* + ** linux/dma-mapping.h ** + *************************/ + +void dma_unmap_single_attrs(struct device *dev, dma_addr_t addr, + size_t size, + enum dma_data_direction dir, + struct dma_attrs *attrs) { SKIP; } + +void dma_unmap_sg_attrs(struct device *dev, struct scatterlist *sg, + int nents, enum dma_data_direction dir, + struct dma_attrs *attrs) { SKIP; } + + +void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size, + enum dma_data_direction direction) { SKIP; } + +int dma_mapping_error(struct device *dev, dma_addr_t dma_addr) { SKIP; return 0; } + + +/********************* + ** linux/uaccess.h ** + *********************/ + +unsigned long clear_user(void *to, unsigned long n) { TRACE; return 0; } + + +/********************** + ** linux/security.h ** + **********************/ + +void security_task_getsecid(struct task_struct *p, u32 *secid) { TRACE; } + + +/********************* + ** linux/utsname.h ** + *********************/ + +struct new_utsname *init_utsname(void) +{ + static struct new_utsname uts = { .sysname = "Genode.UTS", .release = "1.0" }; + return &uts; +} +struct new_utsname *utsname(void) { TRACE; return NULL; } + + +/********************* + ** linux/freezer.h ** + *********************/ + +void set_freezable(void) { TRACE; } + + +/********************* + ** linux/vmalloc.h ** + *********************/ + +void *vmalloc(unsigned long size) { TRACE; return 0; } + + +/******************************** + ** linux/regulator/consumer.h ** + ********************************/ +struct regulator; +int regulator_enable(struct regulator *r) { TRACE; return 0; } +int regulator_disable(struct regulator *r) { TRACE; return 0; } +void regulator_put(struct regulator *r) { TRACE; } +struct regulator *regulator_get(struct device *dev, const char *id) { TRACE; return 0; } + + +/******************************************* + ** arch/arm/plat-omap/include/plat/usb.h ** + *******************************************/ + +int omap_usbhs_enable(struct device *dev) { TRACE; return 0; } +void omap_usbhs_disable(struct device *dev) { TRACE; } + + +/********************** + ** linux/inerrupt.h ** + **********************/ + +void tasklet_kill(struct tasklet_struct *t) { TRACE; } + + +/***************** + ** linux/clk.h ** + *****************/ + +struct clk { }; + +struct clk *clk_get(struct device *dev, const char *id) +{ + static struct clk _c; + TRACE; + return &_c; +} + +int clk_enable(struct clk *clk) { TRACE; return 0; } +void clk_disable(struct clk *clk) { TRACE; } +void clk_put(struct clk *clk) { TRACE; } + +struct clk *devm_clk_get(struct device *dev, const char *id) { TRACE; return 0; } +int clk_prepare_enable(struct clk *clk) { TRACE; return 0; } +void clk_disable_unprepare(struct clk *clk) { TRACE; } + + +/******************** + ** linux/bitmap.h ** + ********************/ + +int bitmap_subset(const unsigned long *src1, + const unsigned long *src2, int nbits) { TRACE; return 1; } + +int bitmap_weight(const unsigned long *src, unsigned int nbits) { TRACE; return 0; } + + +/**************************** + ** drivers/usb/core/usb.h ** + ****************************/ + +#include +#include + +const struct attribute_group *usb_interface_groups[1]; +const struct attribute_group *usb_device_groups[1]; +struct usb_driver usbfs_driver; + +DEFINE_MUTEX(usbfs_mutex); + +void usb_create_sysfs_intf_files(struct usb_interface *intf) { TRACE; } +void usb_remove_sysfs_intf_files(struct usb_interface *intf) { TRACE; } + +int usb_create_sysfs_dev_files(struct usb_device *dev) { TRACE; return 0; } +void usb_remove_sysfs_dev_files(struct usb_device *dev) { TRACE; } + +int usb_devio_init(void) { TRACE; return 0; } +void usb_devio_cleanup(void) { TRACE; } + + +/******************* + ** linux/crc16.h ** + *******************/ + +u16 crc16(u16 crc, const u8 *buffer, size_t len) { TRACE; return 0; } + + +/******************* + ** linux/birev.h ** + *******************/ + +u16 bitrev16(u16 in) { TRACE; return 0; } + + +/************************ + ** linux/radix-tree.h ** + ************************/ + +void *radix_tree_lookup(struct radix_tree_root *root, unsigned long index) { TRACE; return 0; } +void *radix_tree_delete(struct radix_tree_root *root, unsigned long index) { TRACE; return 0; } +void radix_tree_preload_end(void) { TRACE; } + +int radix_tree_insert(struct radix_tree_root *root, unsigned long index, void *item) { TRACE; return 0; } +int radix_tree_maybe_preload(gfp_t gfp_mask) { TRACE; return 0; } + +/****************** + ** linux/gpio.h ** + ******************/ + +bool gpio_is_valid(int number) { TRACE; return false; } +void gpio_set_value_cansleep(unsigned gpio, int value) { TRACE; } +int gpio_request_one(unsigned gpio, unsigned long flags, const char *label) { TRACE; return 0; } + +int devm_gpio_request_one(struct device *dev, unsigned gpio, + unsigned long flags, const char *label) { TRACE; return 0; } + + +/********************* + ** linux/of_gpio.h ** + *********************/ + + int of_get_named_gpio(struct device_node *np, + const char *propname, int index) { TRACE; return 0; } + + +/******************** + ** linux/module.h ** + ********************/ + +void module_put(struct module *m) { TRACE; } +void __module_get(struct module *m) { TRACE; } + + +/****************** + ** linux/phy.h ** + ******************/ + +#include +#include + +struct mii_bus *mdiobus_alloc(void) { TRACE; return 0; } +int mdiobus_register(struct mii_bus *bus) { TRACE; return 0; } +void mdiobus_unregister(struct mii_bus *bus) { TRACE; } +void mdiobus_free(struct mii_bus *bus) { TRACE; } + +int phy_init(struct phy *phy) { TRACE; return 0; } +int phy_exit(struct phy *phy) { TRACE; return 0; } +int phy_power_on(struct phy *phy) { TRACE; return 0; } +int phy_power_off(struct phy *phy) { TRACE; return 0; } +int phy_create_lookup(struct phy *phy, const char *con_id, const char *dev_id) { TRACE; return 0; } +void phy_remove_lookup(struct phy *phy, const char *con_id, const char *dev_id) { TRACE; } + +struct usb_phy *devm_usb_get_phy(struct device *dev, enum usb_phy_type type) { TRACE; return 0; } +struct usb_phy *devm_usb_get_phy_dev(struct device *dev, u8 index) { TRACE; return 0; } + +struct usb_phy *usb_get_phy_dev(struct device *dev, u8 index) { TRACE; return 0; } +void usb_put_phy(struct usb_phy *x) { TRACE; } + +struct phy *devm_phy_get(struct device *dev, const char *string) { TRACE; return 0; } + + +/**************** + ** linux/of.h ** + ****************/ + +struct of_dev_auxdata; +unsigned of_usb_get_maximum_speed(struct device_node *np) { TRACE; return 0; } +unsigned of_usb_get_dr_mode(struct device_node *np) { TRACE; return 0; } +int of_platform_populate(struct device_node *n, const struct of_device_id *of, + const struct of_dev_auxdata *a, struct device *d) { TRACE; return 0; } +int of_device_is_compatible(const struct device_node *device, const char *compat) { TRACE; return 1; } + + +/********************** + ** linux/property.h ** + **********************/ + +bool device_property_read_bool(struct device *dev, const char *propname) { TRACE; return false; } +int device_property_read_u8(struct device *dev, const char *propname, u8 *val) { TRACE; return 0; } + +int device_property_read_u32(struct device *dev, const char *propname, u32 *val) { TRACE; return 0; } + + +/****************************** + ** drivers/usb/dwc3/debug.h ** + ******************************/ + +struct dwc3; + +int dwc3_debugfs_init(struct dwc3 *d){ SKIP; return 0; } +void dwc3_debugfs_exit(struct dwc3 *d) { SKIP; } +void dwc3_trace(void (*trace)(struct va_format *), const char *fmt, ...) { SKIP; } + + +/************************** + ** linux/power_supply.h ** + **************************/ + +#include +struct power_supply * +power_supply_register(struct device *parent, const struct power_supply_desc *desc, + const struct power_supply_config *cfg) { TRACE; return 0; } +void power_supply_unregister(struct power_supply *psy) { TRACE; } +int power_supply_powers(struct power_supply *psy, struct device *dev) { TRACE; return 0; } +void *power_supply_get_drvdata(struct power_supply *psy) { TRACE; return 0; } +void power_supply_changed(struct power_supply *psy) { TRACE; } + + +/********************* + ** linux/kobject.h ** + *********************/ + +void kobject_put(struct kobject *kobj) { TRACE; } +struct kobject *kobject_create_and_add(const char *name, struct kobject *kobj) { TRACE; return 0; } + + +int bus_for_each_drv(struct bus_type *bus, struct device_driver *start, void *data, int (*fn)(struct device_driver *, void *)) +{ + TRACE_AND_STOP; + return -1; +} + +void device_set_of_node_from_dev(struct device *dev, const struct device *dev2) +{ + TRACE; +} + +int devm_add_action(struct device *dev, void (*action)(void *), void *data) +{ + TRACE_AND_STOP; + return -1; +} + +int devm_add_action_or_reset(struct device *dev, void (*action)(void *), void *data) +{ + TRACE_AND_STOP; + return -1; +} + +char *devm_kasprintf(struct device *dev, gfp_t gfp, const char *fmt, ...) +{ + TRACE_AND_STOP; + return NULL; +} + +void devres_close_group(struct device *dev, void *id) +{ + TRACE_AND_STOP; +} + +void * devres_open_group(struct device *dev, void *id, gfp_t gfp) +{ + TRACE_AND_STOP; + return NULL; +} + +int devres_release_group(struct device *dev, void *id) +{ + TRACE_AND_STOP; + return -1; +} + +void *idr_get_next(struct idr *idp, int *nextid) +{ + TRACE_AND_STOP; + return NULL; +} + +void idr_remove(struct idr *idp, int id) +{ + TRACE_AND_STOP; +} + +unsigned int jiffies_to_usecs(const unsigned long j) +{ + TRACE_AND_STOP; + return -1; +} + +struct device *kobj_to_dev(struct kobject *kobj) +{ + TRACE_AND_STOP; + return NULL; +} + +ktime_t ktime_mono_to_real(ktime_t mono) +{ + TRACE_AND_STOP; + return -1; +} + +bool mod_delayed_work(struct workqueue_struct *q, struct delayed_work *w, unsigned long v) +{ + TRACE; + return false; +} + +int mutex_lock_killable(struct mutex *lock) +{ + TRACE_AND_STOP; + return -1; +} + +loff_t no_seek_end_llseek(struct file *f, loff_t o, int v) +{ + TRACE_AND_STOP; + return -1; +} + +int pci_alloc_irq_vectors_affinity(struct pci_dev *dev, unsigned int min_vecs, unsigned int max_vecs, unsigned int flags, const struct irq_affinity *affd) +{ + TRACE; + return 1; +} + +void pci_clear_mwi(struct pci_dev *dev) +{ + TRACE_AND_STOP; +} + +void pci_free_irq_vectors(struct pci_dev *dev) +{ + TRACE_AND_STOP; +} + +int pci_reset_function_locked(struct pci_dev *dev) +{ + TRACE_AND_STOP; + return -1; +} + +void reinit_completion(struct completion *x) +{ + TRACE_AND_STOP; +} + +size_t sg_pcopy_from_buffer(struct scatterlist *sgl, unsigned int nents, const void *buf, size_t buflen, off_t skip) +{ + TRACE_AND_STOP; + return -1; +} + +size_t sg_pcopy_to_buffer(struct scatterlist *sgl, unsigned int nents, void *buf, size_t buflen, off_t skip) +{ + TRACE_AND_STOP; + return -1; +} + +struct device_node *usb_of_get_device_node(struct usb_device *hub, int port1) +{ + TRACE; + return NULL; +} + +struct device_node *usb_of_get_interface_node(struct usb_device *udev, u8 config, u8 ifnum) +{ + TRACE_AND_STOP; + return NULL; +} + +bool usb_of_has_combined_node(struct usb_device *udev) +{ + TRACE; + return -1; +} + +void of_node_put(struct device_node *node) +{ + TRACE; +} +int claim_fiq(struct fiq_handler *f) +{ + TRACE_AND_STOP; + return -1; +} +struct fiq_state; +void dwc_otg_fiq_nop(struct fiq_state *state) +{ + TRACE_AND_STOP; +} + +struct dwc_otg_pcd; +typedef struct dwc_otg_pcd dwc_otg_pcd_t; + +void dwc_otg_pcd_disconnect_us(dwc_otg_pcd_t * pcd, int no_of_usecs) +{ + TRACE_AND_STOP; +} + +int dwc_otg_pcd_get_rmwkup_enable(dwc_otg_pcd_t * pcd) +{ + TRACE_AND_STOP; + return -1; +} + +void dwc_otg_pcd_initiate_srp(dwc_otg_pcd_t * pcd) +{ + TRACE_AND_STOP; +} + +void dwc_otg_pcd_remote_wakeup(dwc_otg_pcd_t * pcd, int set) +{ + TRACE_AND_STOP; +} + +void enable_fiq() +{ + TRACE_AND_STOP; +} + +typedef spinlock_t fiq_lock_t; +void fiq_fsm_spin_lock(fiq_lock_t *lock) +{ + TRACE_AND_STOP; +} + +void fiq_fsm_spin_unlock(fiq_lock_t *lock) +{ + TRACE_AND_STOP; +} + +int fiq_fsm_too_late(struct fiq_state *st, int n) +{ + TRACE_AND_STOP; + return -1; +} + +int in_irq() +{ + TRACE_AND_STOP; + return -1; +} + +void local_fiq_disable() +{ + TRACE_AND_STOP; +} + +void local_fiq_enable() +{ + TRACE_AND_STOP; +} + +struct dwc_otg_device; +typedef struct dwc_otg_device dwc_otg_device_t; + +dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_device_t *otg_dev) +{ + TRACE_AND_STOP; + return NULL; +} + +void dwc_otg_pcd_remove(dwc_otg_pcd_t * pcd) +{ + TRACE_AND_STOP; +} + +unsigned long __phys_to_virt(phys_addr_t x) +{ + TRACE_AND_STOP; + return -1; +} + +void set_fiq_handler(void *start, unsigned int length) +{ + TRACE_AND_STOP; +} + +void set_fiq_regs(struct pt_regs const *regs) +{ + TRACE_AND_STOP; +} + +typedef struct platform_device dwc_bus_dev_t; + +int pcd_init(dwc_bus_dev_t *_dev) +{ + TRACE; + return 0; +} + +void pcd_remove(dwc_bus_dev_t *_dev) +{ + TRACE_AND_STOP; +} + +void dwc_otg_fiq_fsm(struct fiq_state *state, int num_channels) +{ + TRACE_AND_STOP; +} + +unsigned char _dwc_otg_fiq_stub; +unsigned char _dwc_otg_fiq_stub_end; + +bool is_acpi_device_node(struct fwnode_handle *fwnode) +{ + TRACE_AND_STOP; + return false; +} + +bool is_of_node(const struct fwnode_handle *fwnode) +{ + TRACE; + return true; +} + +const void *of_device_get_match_data(const struct device *dev) +{ + TRACE; + return NULL; +} + +int of_usb_get_phy_mode(struct device_node *np) +{ + TRACE; + return 0; +} + +int phy_calibrate(struct phy *phy) +{ + TRACE; + return 0; +} + +int phy_set_mode(struct phy *phy, enum phy_mode mode) +{ + TRACE; + return 0; +} + +int platform_device_add_properties(struct platform_device *pdev, const struct property_entry *properties) +{ + TRACE; + return 0; +} + +struct regulator *__must_check devm_regulator_get(struct device *dev, const char *id) { TRACE; return NULL; } +int disable_irq_nosync(unsigned int irq) { TRACE; return 0; } +int enable_irq(unsigned int irq) { TRACE; return 0; } +void flush_workqueue(struct workqueue_struct *wq) { TRACE; } +int ida_simple_get(struct ida *ida, unsigned int start, unsigned int end, gfp_t gfp_mask) { TRACE; return 0; } +void ida_simple_remove(struct ida *ida, unsigned int id) { TRACE; } +int of_alias_get_id(struct device_node *np, const char *stem) { TRACE; return 0; } +int pm_runtime_get(struct device *dev) { TRACE; return 0; } +void pm_runtime_mark_last_busy(struct device *dev) { TRACE; } +int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val) { TRACE; return 0; } +int regmap_write(struct regmap *map, unsigned int reg, unsigned int val) { TRACE; return 0; } +int stmp_reset_block(void __iomem *addr) { TRACE; return 0; } +int usb_gadget_vbus_connect(struct usb_gadget *gadget) { TRACE; return 0; } +int usb_gadget_vbus_disconnect(struct usb_gadget *gadget) { TRACE; return 0; } +void usb_remove_phy(struct usb_phy *phy) { TRACE; } + +struct ci_hdrc; + +int dbg_create_files(struct ci_hdrc *ci) +{ + TRACE; + return 0; +} + +void dbg_remove_files(struct ci_hdrc *ci) +{ + TRACE; +} diff --git a/repos/dde_linux/src/drivers/usb_host/lx_emul.cc b/repos/dde_linux/src/drivers/usb_host/lx_emul.cc new file mode 100644 index 000000000..162b08244 --- /dev/null +++ b/repos/dde_linux/src/drivers/usb_host/lx_emul.cc @@ -0,0 +1,1091 @@ +/* + * \brief Emulation of Linux kernel interfaces + * \author Norman Feske + * \author Sebastian Sumpf + * \date 2012-01-29 + */ + +/* + * Copyright (C) 2012-2017 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +/* Genode includes */ +#include +#include +#include +#include +#include +#include +#include + +/* Local includes */ +#include "signal.h" +#include "lx_emul.h" + +#include +#include +#include +#include + + +#include +#include + +namespace Genode { + class Slab_backend_alloc; + class Slab_alloc; +} + + +unsigned long jiffies; +void lx_backtrace() { Genode::backtrace(); } + + +void pci_dev_put(struct pci_dev *pci_dev) +{ + Genode::destroy(&Lx_kit::env().heap(), pci_dev); +} + + +/************************************* + ** Memory allocation, linux/slab.h ** + *************************************/ + +void *dma_malloc(size_t size) +{ + return Lx::Malloc::dma().alloc_large(size); +} + + +void dma_free(void *ptr) +{ + Lx::Malloc::dma().free_large(ptr); +} + + +void vfree(void *addr) +{ + if (!addr) return; + Lx::Malloc::mem().free_large(addr); +} + + +/****************** + ** linux/kref.h ** + ******************/ + +void kref_init(struct kref *kref) +{ + lx_log(DEBUG_KREF,"%s ref: %p", __func__, kref); + atomic_set(&kref->refcount, 1); +} + + +void kref_get(struct kref *kref) +{ + atomic_inc(&kref->refcount); + lx_log(DEBUG_KREF, "%s ref: %p c: %d", __func__, kref, kref->refcount.counter); +} + + +int kref_put(struct kref *kref, void (*release) (struct kref *kref)) +{ + lx_log(DEBUG_KREF, "%s: ref: %p c: %d", __func__, kref, kref->refcount.counter); + + if(!atomic_dec_return(&kref->refcount)) { + release(kref); + return 1; + } + return 0; +} + + +/********************* + ** linux/uaccess.h ** + *********************/ + +size_t copy_to_user(void *dst, void const *src, size_t len) +{ + if (dst && src && len) + memcpy(dst, src, len); + return 0; +} + + +bool access_ok(int access, void *addr, size_t size) { return 1; } + + +int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) +{ + Genode::String_console sc(buf, size); + sc.vprintf(fmt, args); + + return sc.len(); +} + + +int snprintf(char *buf, size_t size, const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + Genode::String_console sc(buf, size); + sc.vprintf(fmt, args); + va_end(args); + + return sc.len(); +} + + +int scnprintf(char *buf, size_t size, const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + Genode::String_console sc(buf, size); + sc.vprintf(fmt, args); + va_end(args); + + return sc.len(); +} + + +size_t strlen(const char *s) { return Genode::strlen(s); } + + +/***************** + ** linux/gfp.h ** + *****************/ + +unsigned long get_zeroed_page(gfp_t gfp_mask) +{ + return (unsigned long)kzalloc(PAGE_SIZE, 0); +} + + +/****************** + ** linux/log2.h ** + ******************/ + +int ilog2(u32 n) { return Genode::log2(n); } + + +/******************** + ** linux/slab.h ** + ********************/ + + +void *kmem_cache_zalloc(struct kmem_cache *cache, gfp_t flags) +{ + void *ret; + ret = kmem_cache_alloc(cache, flags); + memset(ret, 0, cache->size()); + + return ret; +} + + +/******************** + ** linux/device.h ** + ********************/ + +/** + * Simple driver management class + */ +class Driver : public Genode::List::Element +{ + private: + + struct device_driver *_drv; /* Linux driver */ + + public: + + Driver(struct device_driver *drv) : _drv(drv) + { + list()->insert(this); + } + + /** + * List of all currently registered drivers + */ + static Genode::List *list() + { + static Genode::List _list; + return &_list; + } + + /** + * Match device and drivers + */ + bool match(struct device *dev) + { + /* + * Don't try if buses don't match, since drivers often use 'container_of' + * which might cast the device to non-matching type + */ + if (_drv->bus != dev->bus) + return false; + + bool ret = _drv->bus->match ? _drv->bus->match(dev, _drv) : true; + lx_log(DEBUG_DRIVER, "MATCH: %s ret: %u match: %p %p", + _drv->name, ret, _drv->bus->match, _drv->probe); + return ret; + } + + /** + * Probe device with driver + */ + int probe(struct device *dev) + { + dev->driver = _drv; + + if (dev->bus->probe) + return dev->bus->probe(dev); + else if (_drv->probe) + return _drv->probe(dev); + + return 0; + } +}; + + +int driver_register(struct device_driver *drv) +{ + lx_log(DEBUG_DRIVER, "%s at %p", drv->name, drv); + new (Lx::Malloc::mem()) Driver(drv); + return 0; +} + + +int device_add(struct device *dev) +{ + if (dev->driver) + return 0; + + /* foreach driver match and probe device */ + for (Driver *driver = Driver::list()->first(); driver; driver = driver->next()) + if (driver->match(dev)) { + int ret = driver->probe(dev); + lx_log(DEBUG_DRIVER, "Probe return %d", ret); + + if (!ret) + return 0; + } + + return 0; +} + + +void device_del(struct device *dev) +{ + if (dev->driver && dev->driver->remove) + dev->driver->remove(dev); + + if (dev->bus && dev->bus->remove) + dev->bus->remove(dev); +} + + +int device_register(struct device *dev) +{ + return device_add(dev); +} + + +void device_unregister(struct device *dev) +{ + device_del(dev); + put_device(dev); +} + + +int device_is_registered(struct device *dev) +{ + return 1; +} + + +void device_release_driver(struct device *dev) +{ + /* is usb_unbind_interface(dev); */ + if (dev->driver->remove) + dev->driver->remove(dev); + + dev->driver = nullptr; +} + + +void put_device(struct device *dev) +{ + if (dev->ref) { + dev->ref--; + return; + } + + if (dev->release) + dev->release(dev); + else if (dev->type && dev->type->release) + dev->type->release(dev); +} + + +struct device *get_device(struct device *dev) +{ + dev->ref++; + + return dev; +} + + +void *dev_get_drvdata(const struct device *dev) +{ + return dev->driver_data; +} + + +int dev_set_drvdata(struct device *dev, void *data) +{ + dev->driver_data = data; return 0; +} + + +const char *dev_name(const struct device *dev) { return dev->name; } + + +void *devm_kzalloc(struct device *dev, size_t size, gfp_t gfp) +{ + return kzalloc(size, gfp); +} + + +void *dev_get_platdata(const struct device *dev) +{ + return (void *)dev->platform_data; +} + + +void put_unaligned_le16(u16 val, void *p) +{ + struct __una_u16 *ptr = (struct __una_u16 *)p; + ptr->x = val; +} + +u32 get_unaligned_le32(const void *p) +{ + const struct __una_u32 *ptr = (const struct __una_u32 *)p; + return ptr->x; +} + + +void put_unaligned_le32(u32 val, void *p) +{ + struct __una_u32 *ptr = (struct __una_u32 *)p; + ptr->x = val; +} + + +u64 get_unaligned_le64(const void *p) +{ + const struct __una_u64 *ptr = (const struct __una_u64 *)p; + return ptr->x; +} + + +/********************************** + ** linux/bitops.h, asm/bitops.h ** + **********************************/ + +int fls(int x) +{ + if (!x) + return 0; + + for (int i = 31; i >= 0; i--) + if (x & (1 << i)) + return i + 1; + + return 0; +} + + +/******************* + ** linux/delay.h ** + *******************/ + +#include + +void usleep_range(unsigned long min, unsigned long max) +{ + udelay(min); +} + + +/********* + ** DMA ** + *********/ + +struct dma_pool +{ + size_t size; + int align; +}; + +struct dma_pool *dma_pool_create(const char *name, struct device *d, size_t size, + size_t align, size_t alloc) +{ + lx_log(DEBUG_DMA, "size: %zx align:%zx %p", size, align, __builtin_return_address((0))); + + if (align & (align - 1)) + return 0; + + dma_pool *pool = new(Lx::Malloc::mem()) dma_pool; + pool->align = Genode::log2((int)align); + pool->size = size; + return pool; +} + + +void dma_pool_destroy(struct dma_pool *d) +{ + lx_log(DEBUG_DMA, "close"); + destroy(Lx::Malloc::mem(), d); +} + + +void *dma_pool_alloc(struct dma_pool *d, gfp_t f, dma_addr_t *dma) +{ + void *addr; + addr = dma_alloc_coherent(0, d->size, dma, 0); + + lx_log(DEBUG_DMA, "addr: %p size %zx align %x phys: %lx pool %p", + addr, d->size, d->align, *dma, d); + return addr; +} + + +void *dma_pool_zalloc(struct dma_pool *pool, gfp_t mem_flags, dma_addr_t *handle) +{ + void * ret = dma_pool_alloc(pool, mem_flags, handle); + if (ret) Genode::memset(ret, 0, pool->size); + return ret; +} + + +void *dma_zalloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flag) +{ + void * ret = dma_alloc_coherent(dev, size, dma_handle, flag); + if (ret) Genode::memset(ret, 0, size); + return ret; +} + + +void dma_pool_free(struct dma_pool *d, void *vaddr, dma_addr_t a) +{ + lx_log(DEBUG_DMA, "free: addr %p, size: %zx", vaddr, d->size); + Lx::Malloc::dma().free(vaddr); +} + + +void *dma_alloc_coherent(struct device *, size_t size, dma_addr_t *dma, gfp_t) +{ + void *addr = Lx::Malloc::dma().alloc(size, PAGE_SHIFT, dma); + + if (!addr) + return 0; + + lx_log(DEBUG_DMA, "DMA pool alloc addr: %p size %zx align: %d, phys: %lx", + addr, size, PAGE_SHIFT, *dma); + return addr; +} + + +void dma_free_coherent(struct device *, size_t size, void *vaddr, dma_addr_t) +{ + lx_log(DEBUG_DMA, "free: addr %p, size: %zx", vaddr, size); + Lx::Malloc::dma().free(vaddr); +} + + +/************************* + ** linux/dma-mapping.h ** + *************************/ + +dma_addr_t dma_map_single_attrs(struct device *dev, void *ptr, + size_t size, + enum dma_data_direction dir, + struct dma_attrs *attrs) +{ + dma_addr_t phys = (dma_addr_t)Lx::Malloc::dma().phys_addr(ptr); + + if (phys == ~0UL) + Genode::error("translation virt->phys ", ptr, "->", Genode::Hex(phys), "failed, return ip ", + __builtin_return_address(0)); + + lx_log(DEBUG_DMA, "virt: %p phys: %lx", ptr, phys); + return phys; +} + + +dma_addr_t dma_map_page(struct device *dev, struct page *page, + size_t offset, size_t size, + enum dma_data_direction dir) +{ + lx_log(DEBUG_DMA, "virt: %p phys: %lx offs: %zx", page->virt, page->phys, offset); + return page->phys + offset; +} + + +int dma_map_sg_attrs(struct device *dev, struct scatterlist *sg, + int nents, enum dma_data_direction dir, + struct dma_attrs *attrs) { return nents; } + + +/************************* + ** linux/scatterlist.h ** + *************************/ + +struct scatterlist *sg_next(struct scatterlist *sg) +{ + if (sg->last) + return 0; + + return sg++; +} + + +struct page *sg_page(struct scatterlist *sg) +{ + if (!sg) + return 0; + + return (page *)sg->page_link; +} + + +/***************** + ** linux/smp.h ** + *****************/ + +int smp_call_function_single(int cpu, smp_call_func_t func, void *info, + int wait) { func(info); return 0; } + + +/****************** + ** linux/log2.h ** + ******************/ + + +int rounddown_pow_of_two(u32 n) +{ + return 1U << Genode::log2(n); +} + + +/***************** + ** linux/nls.h ** + *****************/ + +int utf16s_to_utf8s(const wchar_t *pwcs, int len, + enum utf16_endian endian, u8 *s, int maxlen) +{ + /* + * We do not convert to char, we simply copy the UTF16 plane 0 values + */ + u16 *out = (u16 *)s; + u16 *in = (u16 *)pwcs; + int length = Genode::min(len, maxlen / 2); + for (int i = 0; i < length; i++) + out[i] = in[i]; + + return 2 * length; +} + +/********************** + ** linux/notifier.h ** + **********************/ + +int raw_notifier_chain_register(struct raw_notifier_head *nh, + struct notifier_block *n) +{ + struct notifier_block *nl = nh->head; + struct notifier_block *pr = 0; + while (nl) { + if (n->priority > nl->priority) + break; + pr = nl; + nl = nl->next; + } + + n->next = nl; + if (pr) + pr->next = n; + else + nh->head = n; + + return 0; +} + + +int raw_notifier_call_chain(struct raw_notifier_head *nh, + unsigned long val, void *v) +{ + int ret = NOTIFY_DONE; + struct notifier_block *nb = nh->head; + + while (nb) { + + ret = nb->notifier_call(nb, val, v); + if ((ret & NOTIFY_STOP_MASK) == NOTIFY_STOP_MASK) + break; + + nb = nb->next; + } + + return ret; +} + + +int blocking_notifier_chain_register(struct blocking_notifier_head *nh, + struct notifier_block *n) +{ + return raw_notifier_chain_register((struct raw_notifier_head *)nh, n); +} + + +int blocking_notifier_call_chain(struct blocking_notifier_head *nh, + unsigned long val, void *v) +{ + return raw_notifier_call_chain((struct raw_notifier_head *)nh, val, v); +} + + +/******************* + ** linux/timer.h ** + *******************/ + +#include +#include + +signed long schedule_timeout_uninterruptible(signed long timeout) +{ + lx_log(DEBUG_COMPLETION, "%ld\n", timeout); + schedule_timeout(timeout); + return 0; +} + + +/************************ + ** linux/completion.h ** + ************************/ + +#include + + +long __wait_completion(struct completion *work, unsigned long timeout) +{ + Lx::timer_update_jiffies(); + struct process_timer timer { *Lx::scheduler().current() }; + unsigned long expire = timeout + jiffies; + + if (timeout) { + timer_setup(&timer.timer, process_timeout, 0); + mod_timer(&timer.timer, expire); + } + + while (!work->done) { + + if (timeout && expire <= jiffies) return 0; + + Lx::Task * task = Lx::scheduler().current(); + work->task = (void *)task; + task->block_and_schedule(); + } + + if (timeout) del_timer(&timer.timer); + + work->done = 0; + return (expire > jiffies) ? (expire - jiffies) : 1; +} + + +/*********************** + ** linux/workqueue.h ** + ***********************/ + +#include + + +void tasklet_init(struct tasklet_struct *t, void (*f)(unsigned long), unsigned long d) +{ + t->func = f; + t->data = d; +} + + +void tasklet_schedule(struct tasklet_struct *tasklet) +{ + Lx::Work *lx_work = (Lx::Work *)tasklet_wq->task; + lx_work->schedule_tasklet(tasklet); + lx_work->unblock(); +} + + +void tasklet_hi_schedule(struct tasklet_struct *tasklet) +{ + tasklet_schedule(tasklet); +} + + +struct workqueue_struct *create_singlethread_workqueue(char const *name) +{ + workqueue_struct *wq = (workqueue_struct *)kzalloc(sizeof(workqueue_struct), 0); + Lx::Work *work = Lx::Work::alloc_work_queue(&Lx::Malloc::mem(), name); + wq->task = (void *)work; + + return wq; +} + + +struct workqueue_struct *alloc_workqueue(const char *fmt, unsigned int flags, + int max_active, ...) +{ + return create_singlethread_workqueue(fmt); +} + + +/****************** + ** linux/wait.h ** + ******************/ + +#include + + +static Genode::Bit_allocator<1024> id_allocator; + +int idr_alloc(struct idr *idp, void *ptr, int start, int end, gfp_t gfp_mask) +{ + int max = end > 0 ? end - 1 : ((int)(~0U>>1)); /* inclusive upper limit */ + int id; + + /* sanity checks */ + if (start < 0) return -EINVAL; + if (max < start) return -ENOSPC; + + /* allocate id */ + id = id_allocator.alloc(); + if (id == 0) id = id_allocator.alloc(); /* do not use id zero */ + if (id > max) return -ENOSPC; + + if (!(id >= start)) BUG(); + return id; +} + + +int object_is_on_stack(const void *obj) +{ + Genode::Thread::Stack_info info = Genode::Thread::mystack(); + if ((Genode::addr_t)obj <= info.top && + (Genode::addr_t)obj >= info.base) return 1; + return 0; +} + + +int pci_irq_vector(struct pci_dev *dev, unsigned int nr) +{ + return dev->irq; +} + + +static int platform_match(struct device *dev, struct device_driver *drv) +{ + if (!dev->name) + return 0; + + + printk("MATCH %s %s\n", dev->name, drv->name); + return (Genode::strcmp(dev->name, drv->name) == 0); +} + + +static int platform_drv_probe(struct device *_dev) +{ + struct platform_driver *drv = to_platform_driver(_dev->driver); + struct platform_device *dev = to_platform_device(_dev); + + return drv->probe(dev); +} + + +struct bus_type platform_bus_type = { + .name = "platform", +}; + + +int platform_driver_register(struct platform_driver *drv) +{ + /* init plarform_bus_type */ + platform_bus_type.match = platform_match; + platform_bus_type.probe = platform_drv_probe; + + drv->driver.bus = &platform_bus_type; + if (drv->probe) + drv->driver.probe = platform_drv_probe; + + printk("Register: %s\n", drv->driver.name); + return driver_register(&drv->driver); +} + + +struct resource *platform_get_resource(struct platform_device *dev, + unsigned int type, unsigned int num) +{ + unsigned i; + + for (i = 0; i < dev->num_resources; i++) { + struct resource *r = &dev->resource[i]; + + if ((type & r->flags) && num-- == 0) + return r; + } + + return NULL; +} + + +struct resource *platform_get_resource_byname(struct platform_device *dev, + unsigned int type, + const char *name) +{ + unsigned i; + + for (i = 0; i < dev->num_resources; i++) { + struct resource *r = &dev->resource[i]; + + if (type == r->flags && !Genode::strcmp(r->name, name)) + return r; + } + + return NULL; +} + + +int platform_get_irq_byname(struct platform_device *dev, const char *name) +{ + struct resource *r = platform_get_resource_byname(dev, IORESOURCE_IRQ, name); + return r ? r->start : -1; +} + + +int platform_get_irq(struct platform_device *dev, unsigned int num) +{ + struct resource *r = platform_get_resource(dev, IORESOURCE_IRQ, 0); + return r ? r->start : -1; +} + + +int platform_device_register(struct platform_device *pdev) +{ + pdev->dev.bus = &platform_bus_type; + pdev->dev.name = pdev->name; + /*Set parent to ourselfs */ + if (!pdev->dev.parent) + pdev->dev.parent = &pdev->dev; + device_add(&pdev->dev); + return 0; +} + + +struct platform_device *platform_device_alloc(const char *name, int id) +{ + platform_device *pdev = (platform_device *)kzalloc(sizeof(struct platform_device), GFP_KERNEL); + + if (!pdev) + return 0; + + int len = strlen(name); + pdev->name = (char *)kzalloc(len + 1, GFP_KERNEL); + + if (!pdev->name) { + kfree(pdev); + return 0; + } + + memcpy(pdev->name, name, len); + pdev->name[len] = 0; + pdev->id = id; + pdev->dev.dma_mask = (u64*)kzalloc(sizeof(u64), GFP_KERNEL); + + return pdev; +} + + +int platform_device_add_data(struct platform_device *pdev, const void *data, + size_t size) +{ + void *d = NULL; + + if (data && !(d = kmemdup(data, size, GFP_KERNEL))) + return -ENOMEM; + + kfree(pdev->dev.platform_data); + pdev->dev.platform_data = d; + + return 0; +} + + +int platform_device_add(struct platform_device *pdev) +{ + return platform_device_register(pdev); +} + +int platform_device_add_resources(struct platform_device *pdev, + const struct resource *res, unsigned int num) +{ + struct resource *r = NULL; + + if (res) { + r = (resource *)kmemdup(res, sizeof(struct resource) * num, GFP_KERNEL); + if (!r) + return -ENOMEM; + } + + kfree(pdev->resource); + pdev->resource = r; + pdev->num_resources = num; + return 0; +} + + +void *platform_get_drvdata(const struct platform_device *pdev) +{ + return dev_get_drvdata(&pdev->dev); +} + + +void platform_set_drvdata(struct platform_device *pdev, void *data) +{ + dev_set_drvdata(&pdev->dev, data); +} + + +/********************** + ** asm-generic/io.h ** + **********************/ + +void *devm_ioremap_resource(struct device *dev, struct resource *res) +{ + return ioremap(res->start, res->end - res->start); +} + + +/**************** + ** ** + *****/ +int device_property_read_string(struct device *dev, const char *propname, const char **val) +{ + if (Genode::strcmp("dr_mode", propname) == 0) { + *val = "host"; + return 0; + } + + if (DEBUG_DRIVER) Genode::warning("property ", propname, " not found"); + *val = 0; + return -EINVAL; +} + + +/**************** + ** linux/of.h ** + ****************/ + +const void *of_get_property(const struct device_node *node, const char *name, int *lenp) +{ + for (property * p = node ? node->properties : nullptr; p; p = p->next) + if (Genode::strcmp(name, p->name) == 0) return p->value; + + if (DEBUG_DRIVER) Genode::warning("OF property ", name, " not found"); + return nullptr; +} + + +struct property *of_find_property(const struct device_node *np, const char *name, int *lenp) +{ + if (Genode::strcmp("non-zero-ttctrl-ttha", name) == 0) return (property*) 0xdeadbeef; + + if (DEBUG_DRIVER) Genode::warning("Could not find property ", name); + return nullptr; +} + + +struct platform_device *of_find_device_by_node(struct device_node *np) +{ + return container_of(np->dev, struct platform_device, dev); +} + + +const struct of_device_id *of_match_device(const struct of_device_id *matches, + const struct device *dev) +{ + const char * compatible = (const char*) of_get_property(dev->of_node, "compatible", 0); + for (; matches && matches->compatible; matches++) + if (Genode::strcmp(matches->compatible, compatible) == 0) + return matches; + return nullptr; +} + + +int of_parse_phandle_with_args(struct device_node *np, + const char *list_name, + const char *cells_name, + int index, struct of_phandle_args *out_args) +{ + out_args->np = (device_node*) of_get_property(np, "fsl,usbmisc", 0); + out_args->args[0] = 1; + + return 0; +} + + +int match_string(const char * const *array, size_t n, const char *string) +{ + for (size_t i = 0; i < n; i++) + if (Genode::strcmp(string, array[i]) == 0) return i; + return -1; +} + + +int strcmp(const char *a,const char *b) +{ + return Genode::strcmp(a, b); +} + +struct regmap *syscon_regmap_lookup_by_phandle(struct device_node *np, const char *property) { + return (regmap*)of_get_property(np, property, 0); } + + +bool of_property_read_bool(const struct device_node *np, const char *propname) +{ + if (DEBUG_DRIVER) Genode::warning("Could not find bool property ", propname); + return false; +} + + +static usb_phy * __devm_usb_phy = nullptr; + +struct usb_phy *devm_usb_get_phy_by_phandle(struct device *dev, + const char *phandle, u8 index) { + return __devm_usb_phy; } + + +int usb_add_phy_dev(struct usb_phy *phy) { __devm_usb_phy = phy; return 0; } + + +int of_property_read_u32(const struct device_node *np, const char *propname, u32 *out_value) +{ + if (DEBUG_DRIVER) Genode::warning("Could not find property ", propname); + return -EINVAL; +} diff --git a/repos/dde_linux/src/drivers/usb_host/lx_emul.h b/repos/dde_linux/src/drivers/usb_host/lx_emul.h new file mode 100644 index 000000000..8d9d24721 --- /dev/null +++ b/repos/dde_linux/src/drivers/usb_host/lx_emul.h @@ -0,0 +1,1825 @@ +/* + * \brief Emulation of the Linux kernel API + * \author Norman Feske + * \author Sebastian Sumpf + * \date 2012-01-28 + * + * The content of this file, in particular data structures, is partially + * derived from Linux-internal headers. + */ + +/* + * Copyright (C) 2012-2017 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +#ifndef _LX_EMUL_H_ +#define _LX_EMUL_H_ + +#include +#include + +#include + +#define DEBUG_COMPLETION 0 +#define DEBUG_DMA 0 +#define DEBUG_DRIVER 0 +#define DEBUG_KREF 0 +#define DEBUG_LINUX_PRINTK 0 +#define DEBUG_PCI 0 +#define DEBUG_SKB 0 +#define DEBUG_SLAB 0 +#define DEBUG_TIMER 0 +#define DEBUG_THREAD 0 +#define DEBUG_TRACE 0 + +#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) +#define LINUX_VERSION_CODE KERNEL_VERSION(4,4,3) + +#define KBUILD_MODNAME "mod-noname" + +/* lx_printf */ +#include + + +/******************* + ** linux/sizes.h ** + *******************/ + +#define SZ_256K 0x40000 + + +/***************** + ** linux/bcd.h ** + *****************/ + +#define bin2bcd(x) ((((x) / 10) << 4) + (x) % 10) + + +/*************** + ** asm/bug.h ** + ***************/ + +#include + +/***************** + ** asm/param.h ** + *****************/ + +enum { HZ = 100UL }; + + +/****************** + ** asm/atomic.h ** + ******************/ + +#include + + +/******************* + ** linux/types.h ** + *******************/ + +#include + +typedef __u16 __le16; +typedef __u32 __le32; +typedef __u64 __le64; +typedef __u64 __be64; + +typedef int clockid_t; + +typedef unsigned int u_int; +typedef unsigned char u_char; +typedef unsigned long u_long; +typedef uint8_t u_int8_t; +typedef uint16_t u_int16_t; +typedef uint32_t u_int32_t; + +typedef unsigned short ushort; + +typedef unsigned long phys_addr_t; + +typedef unsigned __poll_t; +typedef unsigned slab_flags_t; + + +/********************** + ** linux/compiler.h ** + **********************/ + +#include +#include + +#define __must_hold(x) + +static inline void __read_once_size(const volatile void *p, void *res, int size) +{ + switch (size) { + case 1: *(__u8 *)res = *(volatile __u8 *)p; break; + case 2: *(__u16 *)res = *(volatile __u16 *)p; break; + case 4: *(__u32 *)res = *(volatile __u32 *)p; break; + case 8: *(__u64 *)res = *(volatile __u64 *)p; break; + default: + barrier(); + __builtin_memcpy((void *)res, (const void *)p, size); + barrier(); + } +} + +#ifdef __cplusplus +#define READ_ONCE(x) \ +({ \ + barrier(); \ + x; \ +}) +#else +#define READ_ONCE(x) \ +({ \ + union { typeof(x) __val; char __c[1]; } __u; \ + __read_once_size(&(x), __u.__c, sizeof(x)); \ + __u.__val; \ +}) +#endif + + +/********************* + ** uapi/linux/uuid ** + *********************/ + +typedef struct { __u8 b[16]; } uuid_le; + + +/******************************* + ** linux/byteorder/generic.h ** + *******************************/ + +#include + +struct __una_u16 { u16 x; } __attribute__((packed)); +struct __una_u32 { u32 x; } __attribute__((packed)); +struct __una_u64 { u64 x; } __attribute__((packed)); + +void put_unaligned_le16(u16 val, void *p); +void put_unaligned_le32(u32 val, void *p); +u32 get_unaligned_le32(const void *p); + +u64 get_unaligned_le64(const void *p); + +#define put_unaligned put_unaligned_le32 +#ifdef __LP64__ +#define get_unaligned get_unaligned_le64 +#else +#define get_unaligned get_unaligned_le32 +#endif + + +/**************** + ** asm/page.h ** + ****************/ + +/* + * For now, hardcoded to x86_32 + */ +#define PAGE_SIZE 4096 + +enum { + PAGE_SHIFT = 12, +}; + +struct page +{ + void *virt; + dma_addr_t phys; +}; + + +/******************************* + ** linux/errno.h and friends ** + *******************************/ + +#include + +enum { + EISDIR = 21, + EXFULL = 52, + ERESTART = 53, + ESHUTDOWN = 58, + ECOMM = 70, + EIDRM = 82, + ENOSR = 211, +}; + + +/******************** + ** linux/kernel.h ** + ********************/ + +#include + +char *kasprintf(gfp_t gfp, const char *fmt, ...); +int kstrtouint(const char *s, unsigned int base, unsigned int *res); + +#define clamp(val, min, max) ({ \ + typeof(val) __val = (val); \ + typeof(min) __min = (min); \ + typeof(max) __max = (max); \ + (void) (&__val == &__min); \ + (void) (&__val == &__max); \ + __val = __val < __min ? __min: __val; \ + __val > __max ? __max: __val; }) + +#define rounddown(x, y) ( \ +{ \ + typeof(x) __x = (x); \ + __x - (__x % (y)); \ +}) + +long simple_strtoul(const char *cp, char **endp, unsigned int base); +long simple_strtol(const char *,char **,unsigned int); + +int vsnprintf(char *buf, size_t size, const char *fmt, va_list args); +int vsprintf(char *buf, const char *fmt, va_list args); +int snprintf(char *buf, size_t size, const char *fmt, ...); +int sprintf(char *buf, const char *fmt, ...); +int sscanf(const char *, const char *, ...); +int scnprintf(char *buf, size_t size, const char *fmt, ...); + + +/********************* + ** linux/preempt.h ** + *********************/ + +bool in_softirq(void); + +/********************* + ** linux/jiffies.h ** + *********************/ + +#include + + +/********************* + ** linux/cpumask.h ** + *********************/ + +static inline unsigned num_online_cpus(void) { return 1U; } + + +/****************** + ** linux/log2.h ** + ******************/ + +int ilog2(u32 n); +int rounddown_pow_of_two(u32 n); + + +/******************** + ** linux/kdev_t.h ** + ********************/ + +#define MINORBITS 20 +#define MKDEV(ma,mi) (((ma) << MINORBITS) | (mi)) + + +/******************** + ** linux/printk.h ** + ********************/ + +#define pr_info(fmt, ...) printk(KERN_INFO fmt, ##__VA_ARGS__) +#define pr_err(fmt, ...) printk(KERN_ERR fmt, ##__VA_ARGS__) +#define pr_debug(fmt, ...) printk(KERN_DEBUG fmt, ##__VA_ARGS__) +#define pr_warning(fmt, ...) printk(KERN_WARNING fmt, ##__VA_ARGS__) +#define pr_warn_once pr_warning +#define pr_warn_ratelimited(fmt, ...) printk(KERN_WARNING fmt, ##__VA_ARGS__) +bool printk_ratelimit(); +#define printk_ratelimited(fmt, ...) printk(fmt, ##__VA_ARGS__) +#define printk_once(fmt, ...) printk(fmt, ##__VA_ARGS__) + + +/********************************** + ** linux/bitops.h, asm/bitops.h ** + **********************************/ + +#define BIT(nr) (1UL << (nr)) +#define BITS_PER_LONG (__SIZEOF_LONG__ * 8) +#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG)) +#define BIT_WORD(nr) ((nr) / BITS_PER_LONG) + +int ffs(int x); +int fls(int x); + +#include +#include +#include +#include + +#define ffz(x) __ffs(~(x)) + +static inline unsigned fls_long(unsigned long l) +{ + if (sizeof(l) == 4) + return fls(l); + return fls64(l); +} + +#define test_and_clear_bit(nr, addr) \ + __test_and_clear_bit(nr, (volatile unsigned long *)(addr)) +#define test_and_set_bit(nr, addr) \ + __test_and_set_bit(nr, (volatile unsigned long *)(addr)) +#define set_bit(nr, addr) \ + __set_bit(nr, (volatile unsigned long *)(addr)) +#define clear_bit(nr, addr) \ + __clear_bit(nr, (volatile unsigned long *)(addr)) + +extern unsigned long find_next_bit(const unsigned long *addr, unsigned long size, unsigned long offset); +extern unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size, unsigned long offset); +static inline unsigned long find_next_zero_bit_le(const unsigned long *addr, unsigned long size, unsigned long offset) +{ + return find_next_zero_bit(addr, size, offset); +} + +#define find_first_bit(addr, size) find_next_bit((addr), (size), 0) + +#define for_each_set_bit(bit, addr, size) \ + for ((bit) = find_first_bit((addr), (size)); \ + (bit) < (size); \ + (bit) = find_next_bit((addr), (size), (bit) + 1)) + + +/***************************************** + ** asm-generic/bitops/const_hweight.h ** + *****************************************/ + +#define hweight32(w) __builtin_popcount((unsigned)w) + + +/******************** + ** linux/string.h ** + ********************/ + +#include + +int strtobool(const char *, bool *); + +#define kbasename(path) (path) + +int match_string(const char * const *array, size_t n, const char *string); + +int strcmp(const char *a,const char *b); + + +/***************** + ** linux/nls.h ** + *****************/ + +enum utf16_endian { UTF16_LITTLE_ENDIAN = 1, }; + +int utf16s_to_utf8s(const wchar_t *pwcs, int len, enum utf16_endian endian, u8 *s, int maxlen); + + +/****************** + ** linux/init.h ** + ******************/ + +#include + +#define __initconst + + +/******************** + ** linux/module.h ** + ********************/ + +#define MODULE_SOFTDEP(x) + +#define module_driver(__driver, __register, __unregister, ...) \ + static int __init __driver##_init(void) \ + { \ + return __register(&(__driver) , ##__VA_ARGS__); \ + } \ + module_init(__driver##_init); \ + static void __exit __driver##_exit(void) \ + { \ + __unregister(&(__driver) , ##__VA_ARGS__); \ + } \ + module_exit(__driver##_exit); + +#define postcore_initcall(fn) void postcore_##fn(void) { fn(); } + + +/****************** + ** linux/slab.h ** + ******************/ + +enum { + ARCH_KMALLOC_MINALIGN = 128, +}; + +void *kzalloc(size_t size, gfp_t flags); +void kfree(const void *); +void *kmalloc(size_t size, gfp_t flags); +void *kcalloc(size_t n, size_t size, gfp_t flags); +void *dma_malloc(size_t size); +void dma_free(void *ptr); + +struct kmem_cache; +struct kmem_cache *kmem_cache_create(const char *, size_t, size_t, unsigned long, void (*)(void *)); +void kmem_cache_destroy(struct kmem_cache *); +void *kmem_cache_zalloc(struct kmem_cache *k, gfp_t flags); +void kmem_cache_free(struct kmem_cache *, void *); +void *kmalloc_array(size_t n, size_t size, gfp_t flags); + + +/********************** + ** linux/spinlock.h ** + **********************/ + +#include + + +/******************* + ** linux/mutex.h ** + *******************/ + +#include + + +/******************* + ** linux/rwsem.h ** + *******************/ + +#include + + +/****************** + ** linux/time.h ** + ******************/ + +#include + + +/******************* + ** linux/timer.h ** + *******************/ + +#include + +#define from_timer(var, callback_timer, timer_fieldname) \ + container_of(callback_timer, typeof(*var), timer_fieldname) + +/******************* + ** linux/delay.h ** + *******************/ + +void msleep(unsigned int msecs); +void udelay(unsigned long usecs); +void mdelay(unsigned long usecs); +void usleep_range(unsigned long min, unsigned long max); + + +/*********************** + ** linux/workquque.h ** + ***********************/ + +#include + +enum { + WORK_STRUCT_PENDING_BIT = 0, +}; + + +#define work_data_bits(work) ((unsigned long *)(&(work)->data)) + +#define work_pending(work) \ + test_bit(WORK_STRUCT_PENDING_BIT, work_data_bits(work)) + +#define delayed_work_pending(w) \ + work_pending(&(w)->work) + +#define create_freezable_workqueue(name) \ + alloc_workqueue("%s", WQ_FREEZABLE | \ + WQ_MEM_RECLAIM, 1, (name)) + +extern struct workqueue_struct *system_power_efficient_wq; + + +/****************** + ** linux/wait.h ** + ******************/ + +#define wait_event_interruptible_timeout(wq, condition, timeout) \ +({ \ + _wait_event_timeout(wq, condition, timeout); \ + 1; \ +}) + + +/******************* + ** linux/sched.h ** + *******************/ + +enum { MAX_SCHEDULE_TIMEOUT = (~0U >> 1) }; + +struct task_struct { + char comm[16]; /* needed by usb/core/devio.c, only for debug output */ +}; +signed long schedule_timeout(signed long); +signed long schedule_timeout_uninterruptible(signed long timeout); +void yield(void); + +extern struct task_struct *current; + +void cpu_relax(void); + +#define memalloc_noio_save() 0 +#define memalloc_noio_restore(x) + + +/********************* + ** linux/kthread.h ** + *********************/ + +int kthread_should_stop(void); +int kthread_stop(struct task_struct *k); + +struct task_struct *kthread_run(int (*)(void *), void *, const char *, ...); + + +/********************** + ** linux/notifier.h ** + **********************/ + +enum { + NOTIFY_DONE = 0x0000, + NOTIFY_OK = 0x0001, + NOTIFY_STOP_MASK = 0x8000, +}; + +struct notifier_block { + int (*notifier_call)(struct notifier_block *, unsigned long, void *); + struct notifier_block *next; + int priority; +}; + +struct raw_notifier_head +{ + struct notifier_block *head; +}; + +struct atomic_notifier_head { + spinlock_t lock; + struct notifier_block *head; +}; + +struct blocking_notifier_head { + struct rw_semaphore rwsem; + struct notifier_block *head; +}; + +#define BLOCKING_NOTIFIER_INIT(name) { \ + .rwsem = __RWSEM_INITIALIZER((name).rwsem), .head = NULL } +#define BLOCKING_NOTIFIER_HEAD(name) \ + struct blocking_notifier_head name = BLOCKING_NOTIFIER_INIT(name) + +int blocking_notifier_chain_register(struct blocking_notifier_head *nh, struct notifier_block *nb); +int blocking_notifier_chain_unregister(struct blocking_notifier_head *nh, struct notifier_block *nb); +int blocking_notifier_call_chain(struct blocking_notifier_head *nh, unsigned long val, void *v); +int atomic_notifier_chain_register(struct atomic_notifier_head *nh, struct notifier_block *nb); +int atomic_notifier_chain_unregister(struct atomic_notifier_head *nh, struct notifier_block *nb); + + +/************************* + ** linux/scatterlist.h ** + *************************/ + +#include + +size_t sg_pcopy_from_buffer(struct scatterlist *sgl, unsigned int nents, const void *buf, size_t buflen, off_t skip); +size_t sg_pcopy_to_buffer(struct scatterlist *sgl, unsigned int nents, void *buf, size_t buflen, off_t skip); + + +/********************* + ** linux/kobject.h ** + *********************/ + +#include + + +/******************* + ** linux/sysfs.h ** + *******************/ + +struct attribute { + const char *name; + mode_t mode; +}; + + +struct attribute_group { + const char *name; + struct attribute **attrs; +}; + +#define __ATTR(_name,_mode,_show,_store) { \ + .attr = {.name = #_name, .mode = _mode }, \ + .show = _show, \ + .store = _store, \ +} + +#define __ATTR_NULL { .attr = { .name = NULL } } +#define __ATTR_RO(name) __ATTR_NULL +#define __ATTR_RW(name) __ATTR_NULL +int sysfs_create_group(struct kobject *kobj, const struct attribute_group *grp); +void sysfs_remove_group(struct kobject *kobj, const struct attribute_group *grp); +int sysfs_create_link(struct kobject *kobj, struct kobject *target, const char *name); +void sysfs_remove_link(struct kobject *kobj, const char *name); + + +/**************** + ** linux/pm.h ** + ****************/ + +#include + +#define PMSG_AUTO_SUSPEND ((struct pm_message) \ + { .event = PM_EVENT_AUTO_SUSPEND, }) + +struct pm_ops_dummy {}; + +#define SET_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) +#define SET_RUNTIME_PM_OPS(suspend_fn, resume_fn, idle_fn) +#define SIMPLE_DEV_PM_OPS(name, suspend_fn, resume_fn) struct pm_ops_dummy name; + + +/************************ + ** linux/pm_runtime.h ** + ************************/ + +int pm_runtime_get(struct device *dev); +bool pm_runtime_active(struct device *dev); +int pm_runtime_set_active(struct device *dev); +void pm_suspend_ignore_children(struct device *dev, bool enable); +void pm_runtime_enable(struct device *dev); +void pm_runtime_disable(struct device *dev); +void pm_runtime_allow(struct device *dev); +void pm_runtime_forbid(struct device *dev); +void pm_runtime_set_suspended(struct device *dev); +void pm_runtime_get_noresume(struct device *dev); +void pm_runtime_put_noidle(struct device *dev); +void pm_runtime_use_autosuspend(struct device *dev); +int pm_runtime_put_sync_autosuspend(struct device *dev); +void pm_runtime_no_callbacks(struct device *dev); +void pm_runtime_set_autosuspend_delay(struct device *dev, int delay); +int pm_runtime_get_sync(struct device *dev); +int pm_runtime_put_sync(struct device *dev); +int pm_runtime_put(struct device *dev); +int pm_runtime_barrier(struct device *dev); +void pm_runtime_mark_last_busy(struct device *dev); + + +/*********************** + ** linux/pm_wakeup.h ** + ***********************/ + +int device_init_wakeup(struct device *dev, bool val); +int device_wakeup_enable(struct device *dev); +bool device_may_wakeup(struct device *dev); +int device_set_wakeup_enable(struct device *dev, bool enable); +bool device_can_wakeup(struct device *dev); + + +/******************** + ** linux/pm_qos.h ** + ********************/ + +enum { PM_QOS_FLAG_NO_POWER_OFF = 1 }; +enum dev_pm_qos_req_type { DEV_PM_QOS_FLAGS = 3 }; + +struct dev_pm_qos_request { unsigned dummy; }; + +int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req, enum dev_pm_qos_req_type type, s32 value); +int dev_pm_qos_remove_request(struct dev_pm_qos_request *req); +int dev_pm_qos_expose_flags(struct device *dev, s32 value); + + +/****************** + ** linux/acpi.h ** + ******************/ + +struct fwnode_handle; + +bool is_acpi_device_node(struct fwnode_handle *fwnode); +#define ACPI_PTR(_ptr) (NULL) + + +/******************** + ** linux/device.h ** + ********************/ + +#define dev_info(dev, format, arg...) lx_printf("dev_info: " format, ## arg) +#define dev_warn(dev, format, arg...) lx_printf("dev_warn: " format, ## arg) +#define dev_WARN(dev, format, arg...) lx_printf("dev_WARN: " format, ## arg) +#define dev_err( dev, format, arg...) lx_printf("dev_error: " format, ## arg) +#define dev_dbg_ratelimited(dev, format, arg...) + +#define dev_WARN_ONCE(dev, condition, format, arg...) ({\ + lx_printf("dev_WARN_ONCE: " format, ## arg); \ + !!condition; \ +}) + +#if DEBUG_LINUX_PRINTK +#define dev_dbg(dev, format, arg...) lx_printf("dev_dbg: " format, ## arg) +#define CONFIG_DYNAMIC_DEBUG 1 +#else +#define dev_dbg( dev, format, arg...) +#endif + +#define dev_printk(level, dev, format, arg...) \ + lx_printf("dev_printk: " format, ## arg) + +#define dev_warn_ratelimited(dev, format, arg...) \ + lx_printf("dev_warn_ratelimited: " format "\n", ## arg) + +#define dev_warn_once(dev, format, ...) \ + lx_printf("dev_warn_ratelimited: " format "\n", ##__VA_ARGS__) + +enum { + BUS_NOTIFY_ADD_DEVICE = 0x00000001, + BUS_NOTIFY_DEL_DEVICE = 0x00000002, +}; + +struct device; +struct device_driver; + +struct bus_type { + const char *name; + struct device_attribute *dev_attrs; + const struct attribute_group **dev_groups; + const struct attribute_group **drv_groups; + + int (*match)(struct device *dev, struct device_driver *drv); + int (*uevent)(struct device *dev, struct kobj_uevent_env *env); + int (*probe)(struct device *dev); + int (*remove)(struct device *dev); +}; + +struct device_driver { + char const *name; + struct bus_type *bus; + struct module *owner; + const char *mod_name; + const struct of_device_id *of_match_table; + const struct acpi_device_id *acpi_match_table; + int (*probe) (struct device *dev); + int (*remove) (struct device *dev); + + const struct dev_pm_ops *pm; +}; + +struct device_type { + const char *name; + const struct attribute_group **groups; + void (*release)(struct device *dev); + int (*uevent)(struct device *dev, struct kobj_uevent_env *env); + char *(*devnode)(struct device *dev, mode_t *mode, kuid_t *, kgid_t *); + const struct dev_pm_ops *pm; +}; + +struct class +{ + const char *name; + char *(*devnode)(struct device *dev, mode_t *mode); +}; + +struct device { + const char *name; + struct device *parent; + struct kobject kobj; + const struct device_type *type; + struct device_driver *driver; + void *platform_data; + u64 _dma_mask_buf; + u64 *dma_mask; /* needed by usb/hcd.h */ + u64 coherent_dma_mask; /* omap driver */ + unsigned long dma_pfn_offset; + struct dev_pm_info power; + dev_t devt; + const struct attribute_group **groups; + void (*release)(struct device *dev); + struct bus_type *bus; + struct class *class; + void *driver_data; + struct device_node *of_node; + struct fwnode_handle *fwnode; + struct device_dma_parameters *dma_parms; + unsigned ref; +}; + +struct device_attribute { + struct attribute attr; + ssize_t (*show)(struct device *dev, struct device_attribute *attr, + char *buf); + ssize_t (*store)(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count); +}; + +struct driver_attribute { + struct attribute attr; + ssize_t (*show)(struct device_driver *driver, char *buf); + ssize_t (*store)(struct device_driver *driver, const char *buf, + size_t count); +}; + +struct lock_class_key { int dummy; }; + +#define DEVICE_ATTR(_name, _mode, _show, _store) \ +struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store) + +#define DEVICE_ATTR_RO(_name) \ +struct device_attribute dev_attr_##_name = __ATTR_RO(_name) + +#define DEVICE_ATTR_RW(_name) \ +struct device_attribute dev_attr_##_name = __ATTR_RW(_name) + +#define DRIVER_ATTR_RW(_name) \ +struct driver_attribute driver_attr_##_name = __ATTR_RW(_name) + +#define DRIVER_ATTR_RO(_name) \ +struct driver_attribute driver_attr_##_name = __ATTR_RO(_name) + +void *dev_get_drvdata(const struct device *dev); +int dev_set_drvdata(struct device *dev, void *data); +int dev_set_name(struct device *dev, const char *name, ...); +const char *dev_name(const struct device *dev); +int dev_to_node(struct device *dev); +void set_dev_node(struct device *dev, int node); + +struct device *device_create(struct class *cls, struct device *parent, dev_t devt, void *drvdata, const char *fmt, ...); +int device_add(struct device *dev); +void device_destroy(struct class *cls, dev_t devt); +int device_register(struct device *dev); +void device_unregister(struct device *dev); +void device_lock(struct device *dev); +int device_trylock(struct device *dev); +void device_unlock(struct device *dev); +void device_del(struct device *dev); +void device_initialize(struct device *dev); +int device_attach(struct device *dev); +int device_is_registered(struct device *dev); +int device_bind_driver(struct device *dev); +void device_release_driver(struct device *dev); +void device_enable_async_suspend(struct device *dev); +void device_set_wakeup_capable(struct device *dev, bool capable); +int device_create_file(struct device *device, const struct device_attribute *entry); +void device_remove_file(struct device *dev, const struct device_attribute *attr); +int device_for_each_child(struct device *dev, void *data, + int (*fn)(struct device *dev, void *data)); +void put_device(struct device *dev); +struct device *get_device(struct device *dev); +int driver_register(struct device_driver *drv); +void driver_unregister(struct device_driver *drv); +int driver_attach(struct device_driver *drv); +int driver_create_file(struct device_driver *driver, const struct driver_attribute *attr); +void driver_remove_file(struct device_driver *driver, const struct driver_attribute *attr); +struct device *bus_find_device(struct bus_type *bus, struct device *start, void *data, int (*match)(struct device *dev, void *data)); +int bus_register(struct bus_type *bus); +void bus_unregister(struct bus_type *bus); +int bus_register_notifier(struct bus_type *bus, struct notifier_block *nb); +int bus_unregister_notifier(struct bus_type *bus, struct notifier_block *nb); +int bus_for_each_dev(struct bus_type *bus, struct device *start, void *data, int (*fn)(struct device *dev, void *data)); +struct class *__class_create(struct module *owner, const char *name, struct lock_class_key *key); +#define class_create(owner, name) \ +({ \ + static struct lock_class_key __key; \ + __class_create(owner, name, &__key); \ +}) +void class_destroy(struct class *cls); +void *devm_kzalloc(struct device *dev, size_t size, gfp_t gfp); +struct resource; +void *devm_ioremap_resource(struct device *dev, struct resource *res); +void *dev_get_platdata(const struct device *dev); +void device_set_of_node_from_dev(struct device *dev, const struct device *dev2); + + +/***************************** + ** linux/platform_device.h ** + *****************************/ + +#define module_platform_driver(__platform_driver) \ + module_driver(__platform_driver, platform_driver_register, \ + platform_driver_unregister) + +enum { PLATFORM_DEVID_AUTO = -2 }; + +struct platform_device { + char * name; + int id; + struct device dev; + u32 num_resources; + struct resource *resource; +}; + +struct platform_device *platform_device_alloc(const char *name, int id); +int platform_device_add(struct platform_device *pdev); +int platform_device_del(struct platform_device *pdev); +int platform_device_put(struct platform_device *pdev); +int platform_device_register(struct platform_device *); +void platform_device_unregister(struct platform_device *); +void *platform_get_drvdata(const struct platform_device *pdev); +void platform_set_drvdata(struct platform_device *pdev, void *data); +int platform_device_add_data(struct platform_device *pdev, const void *data, size_t size); +int platform_device_add_resources(struct platform_device *pdev, const struct resource *res, unsigned int num); + +int platform_get_irq(struct platform_device *, unsigned int); +int platform_get_irq_byname(struct platform_device *, const char *); +struct resource *platform_get_resource(struct platform_device *, unsigned, unsigned); +struct resource *platform_get_resource_byname(struct platform_device *, unsigned int, const char *); + +struct platform_driver { + int (*probe)(struct platform_device *); + int (*remove)(struct platform_device *); + void (*shutdown)(struct platform_device *); + struct device_driver driver; + const struct platform_device_id *id_table; +}; + +int platform_driver_register(struct platform_driver *); +void platform_driver_unregister(struct platform_driver *); + +struct property_entry; +int platform_device_add_properties(struct platform_device *pdev, const struct property_entry *properties); + +#define to_platform_driver(drv) (container_of((drv), struct platform_driver, \ + driver)) + +#define to_platform_device(x) container_of((x), struct platform_device, dev) + + +/********************* + ** linux/dmapool.h ** + *********************/ + +struct dma_pool; + +struct dma_pool *dma_pool_create(const char *, struct device *, size_t, size_t, size_t); +void dma_pool_destroy(struct dma_pool *); +void *dma_pool_alloc(struct dma_pool *, gfp_t, dma_addr_t *); +void dma_pool_free(struct dma_pool *, void *, dma_addr_t); +void *dma_pool_zalloc(struct dma_pool *pool, gfp_t mem_flags, dma_addr_t *handle); +void *dma_alloc_coherent(struct device *, size_t, dma_addr_t *, gfp_t); +void dma_free_coherent(struct device *, size_t, void *, dma_addr_t); + + +/************************* + ** linux/dma-mapping.h ** + *************************/ + +#define DMA_BIT_MASK(n) (((n) == 64) ? ~0ULL : ((1ULL<<(n))-1)) + +static inline int dma_set_coherent_mask(struct device *dev, u64 mask) +{ + dev->coherent_dma_mask = mask; + return 0; +} + +static inline int dma_set_mask(struct device *dev, u64 mask) { *dev->dma_mask = mask; return 0; } + +static inline int dma_coerce_mask_and_coherent(struct device *dev, u64 mask) +{ + dma_set_mask(dev, mask); + return dma_set_coherent_mask(dev, mask); +} + +static inline int dma_set_mask_and_coherent(struct device *dev, u64 mask) +{ + dma_set_mask(dev, mask); + dma_set_coherent_mask(dev, mask); + return 0; +} + +void *dma_zalloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flag); + + +/********************* + ** linux/uaccess.h ** + *********************/ + +enum { VERIFY_READ = 0, VERIFY_WRITE = 1 }; + +bool access_ok(int access, void *addr, size_t size); + +size_t copy_to_user(void *dst, void const *src, size_t len); + + +/***************** + ** linux/dmi.h ** + *****************/ + +struct dmi_system_id; + +static inline int dmi_check_system(const struct dmi_system_id *list) { return 0; } +static inline const char * dmi_get_system_info(int field) { return NULL; } + + +/****************** + ** linux/poll.h ** + ******************/ + +typedef struct poll_table_struct { int dummy; } poll_table; + +struct file; + +void poll_wait(struct file *, wait_queue_head_t *, poll_table *); + + +/******************** + ** linux/statfs.h ** + ********************/ + +loff_t default_llseek(struct file *file, loff_t offset, int origin); + + +/**************** + ** linux/fs.h ** + ****************/ + +struct dentry; +struct file_operations; + +struct path { + struct dentry *dentry; +}; + +struct file { + u64 f_version; + loff_t f_pos; + struct dentry *f_dentry; + struct path f_path; + unsigned int f_flags; + fmode_t f_mode; + const struct file_operations *f_op; + void *private_data; +}; + +struct inode; + +struct file_operations { + struct module *owner; + int (*open) (struct inode *, struct file *); + ssize_t (*read) (struct file *, char __user *, size_t, loff_t *); + loff_t (*llseek) (struct file *, loff_t, int); + unsigned int (*poll) (struct file *, struct poll_table_struct *); + int (*release) (struct inode *, struct file *); +}; + +struct inode { + void *i_private; +}; +unsigned iminor(const struct inode *inode); +static inline struct file_operations const * fops_get(struct file_operations const *fops) { return fops; } +void fops_put(struct file_operations const *); +loff_t noop_llseek(struct file *file, loff_t offset, int origin); +int register_chrdev(unsigned int major, const char *name, const struct file_operations *fops); +void unregister_chrdev(unsigned int major, const char *name); +ssize_t simple_read_from_buffer(void __user *to, size_t count, loff_t *ppos, const void *from, size_t available); + +#define replace_fops(f, fops) \ +do { \ + struct file *__file = (f); \ + fops_put(__file->f_op); \ + BUG_ON(!(__file->f_op = (fops))); \ +} while(0) + +loff_t no_seek_end_llseek(struct file *, loff_t, int); + + +/********************** + ** linux/seq_file.h ** + **********************/ + +struct seq_file { int dummy; }; + + +/***************** + ** linux/gfp.h ** + *****************/ + +#include + +enum { + GFP_NOIO = GFP_LX_DMA, +}; + +unsigned long get_zeroed_page(gfp_t gfp_mask); +unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order); +void free_pages(unsigned long addr, unsigned int order); +#define free_page(addr) free_pages((addr), 0) + + +/******************** + * linux/debugfs.h ** + ********************/ + +struct dentry *debugfs_create_dir(const char *name, struct dentry *parent); +struct dentry *debugfs_create_file(const char *name, mode_t mode, struct dentry *parent, void *data, const struct file_operations *fops); +void debugfs_remove(struct dentry *dentry); +static inline void debugfs_remove_recursive(struct dentry *dentry) { } + +struct debugfs_regset32 {}; + + +/************************ + ** linux/page-flags.h ** + ************************/ + +bool is_highmem(void *); +#define PageHighMem(__p) is_highmem(page_zone(__p)) + + +/**************** + ** linux/mm.h ** + ****************/ + +struct zone *page_zone(const struct page *page); +int is_vmalloc_addr(const void *x); + + +/********************** + ** asm-generic/io.h ** + **********************/ + +#include + +void *ioremap(phys_addr_t addr, unsigned long size); +void iounmap(volatile void *addr); + +#define ioremap_nocache ioremap + +void outb(u8 value, u32 port); +void outw(u16 value, u32 port); +void outl(u32 value, u32 port); + +u8 inb(u32 port); +u16 inw(u32 port); +u32 inl(u32 port); + +void native_io_delay(void); + +static inline void outb_p(u8 value, u32 port) { outb(value, port); native_io_delay(); } +static inline void outl_p(u32 value, u32 port) { outl(value, port); native_io_delay(); } +static inline u8 inb_p(u32 port) { u8 ret = inb(port); native_io_delay(); return ret; } +static inline u32 inl_p(u32 port) { u32 ret = inl(port); native_io_delay(); return ret; } + +#define readl_relaxed readl +#define writel_relaxed writel + +#define ioread32(addr) readl(addr) +#define iowrite32(v, addr) writel((v), (addr)) + + +/******************** + ** linux/ioport.h ** + ********************/ + +#include + + +/*********************** + ** linux/irqreturn.h ** + ***********************/ + +#include + +#define IRQ_RETVAL(x) ((x) != IRQ_NONE) + +int devm_request_irq(struct device *dev, unsigned int irq, irq_handler_t handler, unsigned long irqflags, const char *devname, void *dev_id); + + +/*********************** + ** linux/interrupt.h ** + ***********************/ + +enum { + IRQF_SHARED = 0x00000080, +}; + +void local_irq_enable(void); +void local_irq_disable(void); +int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, const char *name, void *dev); +void free_irq(unsigned int, void *); +int disable_irq_nosync(unsigned int irq); +int enable_irq(unsigned int irq); +void disable_irq(unsigned int irq); + + +/********************* + ** linux/hardirq.h ** + *********************/ + +int in_irq(); +bool in_interrupt(void); +void synchronize_irq(unsigned int irq); + + +/*************** + ** asm/fiq.h ** + ***************/ + +struct fiq_handler { + char const *name; +}; + +struct pt_regs; + +int claim_fiq(struct fiq_handler *f); +void set_fiq_handler(void *start, unsigned int length); +void set_fiq_regs(struct pt_regs const *regs); +void enable_fiq(); + + +/***************** + ** linux/pci.h ** + *****************/ + +extern struct bus_type pci_bus_type; + +enum { DEVICE_COUNT_RESOURCE = 6 }; + +struct pci_dev { + unsigned int devfn; + unsigned int irq; + struct resource resource[DEVICE_COUNT_RESOURCE]; + struct pci_bus *bus; + unsigned short vendor; + unsigned short device; + unsigned short subsystem_vendor; + unsigned short subsystem_device; + unsigned int class; + u8 revision; + u8 pcie_cap; + u16 pcie_flags_reg; + struct device dev; + unsigned current_state; +}; + +struct pci_fixup { + u16 vendor; /* You can use PCI_ANY_ID here of course */ + u16 device; /* You can use PCI_ANY_ID here of course */ + u32 class; /* You can use PCI_ANY_ID here too */ + unsigned int class_shift; /* should be 0, 8, 16 */ + void (*hook)(struct pci_dev *dev); +}; + +#include +#include + +#define PCI_DEVICE_CLASS(dev_class,dev_class_mask) \ + .class = (dev_class), .class_mask = (dev_class_mask), \ + .vendor = PCI_ANY_ID, .device = PCI_ANY_ID, \ + .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID + +#define PCI_DEVICE(vend,dev) \ + .vendor = (vend), .device = (dev), \ + .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID + +#define PCI_VDEVICE(vendor, device) \ + PCI_VENDOR_ID_##vendor, (device), \ + PCI_ANY_ID, PCI_ANY_ID, 0, 0 + +#define DECLARE_PCI_FIXUP_CLASS_FINAL(vendor, device, class, \ + class_shift, hook) \ + void __pci_fixup_##hook(void *data) { hook(data); } + +#define for_each_pci_dev(d) printk("for_each_pci_dev called\n"); while(0) + +enum { PCI_ROM_RESOURCE = 6 }; + +int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask); +int pci_set_power_state(struct pci_dev *dev, pci_power_t state); +void pci_clear_mwi(struct pci_dev *dev); + +struct irq_affinity; + +int pci_reset_function_locked(struct pci_dev *dev); +int pci_alloc_irq_vectors_affinity(struct pci_dev *dev, unsigned int min_vecs, unsigned int max_vecs, unsigned int flags, const struct irq_affinity *affd); +void pci_free_irq_vectors(struct pci_dev *dev); +int pci_irq_vector(struct pci_dev *dev, unsigned int nr); + +static inline int pci_alloc_irq_vectors(struct pci_dev *dev, unsigned int min_vecs, + unsigned int max_vecs, unsigned int flags) +{ + return pci_alloc_irq_vectors_affinity(dev, min_vecs, max_vecs, flags, NULL); +} + +enum { + PCI_IRQ_MSI = (1 << 1), + PCI_IRQ_MSIX = (1 << 2), +}; + + +/********************** + ** linux/irqflags.h ** + **********************/ + +unsigned long local_irq_save(unsigned long flags); +unsigned long local_irq_restore(unsigned long flags); +void local_fiq_disable(); +void local_fiq_enable(); +unsigned smp_processor_id(void); + + +/************************* + ** linux/dma-direction ** + *************************/ + +enum dma_data_direction +{ + DMA_BIDIRECTIONAL = 0, + DMA_TO_DEVICE = 1, + DMA_FROM_DEVICE = 2 +}; + + +/************************* + ** linux/dma-mapping.h ** + *************************/ + +struct dma_attrs; + +dma_addr_t dma_map_single_attrs(struct device *dev, void *ptr, size_t size, enum dma_data_direction dir, struct dma_attrs *attrs); + +void dma_unmap_single_attrs(struct device *dev, dma_addr_t addr, size_t size, enum dma_data_direction dir, struct dma_attrs *attrs); + +void dma_unmap_sg_attrs(struct device *dev, struct scatterlist *sg, int nents, enum dma_data_direction dir, struct dma_attrs *attrs); + +dma_addr_t dma_map_page(struct device *dev, struct page *page, size_t offset, size_t size, enum dma_data_direction dir); + +int dma_map_sg_attrs(struct device *dev, struct scatterlist *sg, int nents, enum dma_data_direction dir, struct dma_attrs *attrs); + +#define dma_map_single(d, a, s, r) dma_map_single_attrs(d, a, s, r, NULL) +#define dma_unmap_single(d, a, s, r) dma_unmap_single_attrs(d, a, s, r, NULL) +#define dma_map_sg(d, s, n, r) dma_map_sg_attrs(d, s, n, r, NULL) +#define dma_unmap_sg(d, s, n, r) dma_unmap_sg_attrs(d, s, n, r, NULL) + +void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size, enum dma_data_direction direction); +int dma_mapping_error(struct device *dev, dma_addr_t dma_addr); +static inline int is_device_dma_capable(struct device *dev) { return *dev->dma_mask; } + + +/****************** + ** linux/stat.h ** + ******************/ + +enum { + S_IRUGO = 444, +}; + +#include + + +/********************* + ** linux/utsname.h ** + *********************/ + +#define __NEW_UTS_LEN 64 + +struct new_utsname { + char sysname[__NEW_UTS_LEN + 1]; + char release[__NEW_UTS_LEN + 1]; +}; + +struct new_utsname *init_utsname(void); + + +/************************ + ** linux/completion.h ** + ************************/ + +#include + +struct completion { unsigned int done; void *task; }; +long __wait_completion(struct completion *work, unsigned long timeout);; +void reinit_completion(struct completion *x); + + +/****************** + ** linux/list.h ** + ******************/ + +#include + + +/******************** + ** linux/random.h ** + ********************/ + +void add_device_randomness(const void *, unsigned int); + + +/********************* + ** linux/vmalloc.h ** + *********************/ + +void *vmalloc(unsigned long size); +void vfree(void *addr); + + +/********************** + ** linux/inerrupt.h ** + **********************/ + +extern struct workqueue_struct *tasklet_wq; + +struct tasklet_struct +{ + void (*func)(unsigned long); + unsigned long data; + unsigned pending; +}; + +void tasklet_schedule(struct tasklet_struct *t); +void tasklet_hi_schedule(struct tasklet_struct *t); +void tasklet_init(struct tasklet_struct *t, void (*)(unsigned long), unsigned long); + + +/***************** + ** linux/idr.h ** + *****************/ + +#define DEFINE_IDA(name) struct ida name; +struct ida { }; + +int ida_simple_get(struct ida *ida, unsigned int start, unsigned int end, + gfp_t gfp_mask); +void ida_simple_remove(struct ida *ida, unsigned int id); + +struct idr { int dummy; }; + +int idr_alloc(struct idr *idp, void *ptr, int start, int end, gfp_t gfp_mask); +void idr_remove(struct idr *idp, int id); +void idr_destroy(struct idr *); +void *idr_get_next(struct idr *idp, int *nextid); + +#define idr_for_each_entry(idp, entry, id) \ + for (id = 0; ((entry) = idr_get_next(idp, &(id))) != NULL; ++id) + +#define IDR_INIT(name) { .dummy = 0, } +#define DEFINE_IDR(name) struct idr name = IDR_INIT(name) + + +/******************************* + ** uapi/linux/usbdevice_fs.h ** + *******************************/ + +enum { USBDEVFS_HUB_PORTINFO }; + +struct usbdevfs_hub_portinfo +{ + char nports; + char port [127]; +}; + + +/******************** + ** linux/bitmap.h ** + ********************/ + +#define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) & (BITS_PER_LONG - 1))) +#define BITMAP_LAST_WORD_MASK(nbits) (~0UL >> (-(nbits) & (BITS_PER_LONG - 1))) + + +/****************** + ** linux/phy.h ** + ******************/ + +struct phy; + +enum phy_mode { + PHY_MODE_INVALID, + PHY_MODE_USB_HOST, + PHY_MODE_USB_DEVICE, + PHY_MODE_USB_OTG, + PHY_MODE_SGMII, + PHY_MODE_10GKR, + PHY_MODE_UFS_HS_A, + PHY_MODE_UFS_HS_B, +}; + +int phy_init(struct phy *phy); +int phy_exit(struct phy *phy); +struct phy *phy_get(struct device *dev, const char *string); +void phy_put(struct phy *phy); +int phy_power_on(struct phy *phy); +int phy_power_off(struct phy *phy); + +struct phy *devm_phy_get(struct device *dev, const char *string); +struct phy *devm_of_phy_get(struct device *dev, struct device_node *np, const char *con_id); + +int phy_create_lookup(struct phy *phy, const char *con_id, const char *dev_id); +void phy_remove_lookup(struct phy *phy, const char *con_id, const char *dev_id); + +int phy_set_mode(struct phy *phy, enum phy_mode mode); +int phy_calibrate(struct phy *phy); + + +/************************ + ** linux/usb/gadget.h ** + ************************/ + +struct usb_ep { }; +struct usb_request { }; +struct usb_gadget { struct device dev; }; + +int usb_gadget_vbus_connect(struct usb_gadget *gadget); +int usb_gadget_vbus_disconnect(struct usb_gadget *gadget); + + +/********************************* + ** linux/usb/usb_phy_generic.h ** + *********************************/ + +struct usb_phy_generic_platform_data +{ + int type; + int gpio_reset; +}; + + +/**************** + ** linux/of.h ** + ****************/ + +struct property { + const char * name; + void * value; + struct property * next; +}; + +struct device_node { + struct property * properties; + struct device * dev; +}; + +struct of_phandle_args { + struct device_node *np; + int args_count; + uint32_t args[32]; +}; + +bool of_property_read_bool(const struct device_node *np, const char *propname); +void of_node_put(struct device_node *node); +int of_device_is_compatible(const struct device_node *device, const char *); +int of_property_read_u32(const struct device_node *np, const char *propname, u32 *out_value); +bool is_of_node(const struct fwnode_handle *fwnode); +const void *of_get_property(const struct device_node *node, const char *name, int *lenp); +int of_parse_phandle_with_args(struct device_node *np, const char *list_name, const char *cells_name, int index, struct of_phandle_args *out_args); +const struct of_device_id *of_match_device(const struct of_device_id *matches, const struct device *dev); +extern struct platform_device *of_find_device_by_node(struct device_node *np); +struct property *of_find_property(const struct device_node *np, const char *name, int *lenp); + +#define of_match_ptr(ptr) NULL +#define for_each_available_child_of_node(parent, child) while (0) + +const void *of_device_get_match_data(const struct device *dev); +int of_alias_get_id(struct device_node *np, const char *stem); + + +/********************* + ** linux/of_gpio.h ** + *********************/ + +int of_get_named_gpio(struct device_node *, const char *, int); + + +/************************* + ** linux/of_platform.h ** + *************************/ + +struct of_dev_auxdata; + +int of_platform_populate(struct device_node *, const struct of_device_id *, + const struct of_dev_auxdata *, struct device *); + + +/****************** + ** linux/gpio.h ** + ******************/ + +enum { GPIOF_OUT_INIT_HIGH = 0x2 }; + +bool gpio_is_valid(int); +int devm_gpio_request_one(struct device *dev, unsigned gpio, unsigned long flags, const char *label); + + +/***************** + ** linux/clk.h ** + *****************/ + +struct clk *devm_clk_get(struct device *dev, const char *id); +int clk_prepare_enable(struct clk *); +void clk_disable_unprepare(struct clk *); + + +/********************** + ** linux/property.h ** + **********************/ + +struct property_entry { const char *name; }; + +int device_property_read_string(struct device *dev, const char *propname, const char **val); +bool device_property_read_bool(struct device *dev, const char *propname); +int device_property_read_u8(struct device *dev, const char *propname, u8 *val); +int device_property_read_u32(struct device *dev, const char *propname, u32 *val); + + +/************************ + ** linux/radix-tree.h ** + ************************/ + +#define INIT_RADIX_TREE(root, mask) lx_printf("INIT_RADIX_TREE not impelemnted\n") +struct radix_tree_root { }; +void *radix_tree_lookup(struct radix_tree_root *root, unsigned long index); +int radix_tree_insert(struct radix_tree_root *, unsigned long, void *); +void *radix_tree_delete(struct radix_tree_root *, unsigned long); +void radix_tree_preload_end(void); +int radix_tree_maybe_preload(gfp_t gfp_mask); + + +/****************** + ** asm/ptrace.h ** + ******************/ + +struct pt_regs { unsigned long dummy; }; + +#define ARM_r8 dummy +#define ARM_r9 dummy +#define ARM_sp dummy +#define ARM_fp dummy + + +/***************** + ** linux/smp.h ** + *****************/ + +typedef void (*smp_call_func_t)(void *info); + +int smp_call_function_single(int cpuid, smp_call_func_t func, void *info, + int wait); + + +/*********************** + ** linux/eventpoll.h ** + ***********************/ + +#define EPOLLIN (__force __poll_t)0x00000001 +#define EPOLLRDNORM (__force __poll_t)0x00000040 + + +/****************************** + ** linux/sched/task_stack.h ** + ******************************/ + +int object_is_on_stack(const void *obj); + + +/***************** + ** linux/tty.h ** + *****************/ + +struct tty_port {}; + + +/*********************************** + ** arch/arm/include/asm/memory.h ** + ***********************************/ + +/* + * deprecated internal function not really part of Linux kernel anymore, + * but needed by dwc_otg patches + */ +unsigned long __phys_to_virt(phys_addr_t x); + + +/******************************** + ** linux/regulator/consumer.h ** + ********************************/ + +struct regulator { }; + +int regulator_enable(struct regulator *); +int regulator_disable(struct regulator *); +struct regulator *__must_check devm_regulator_get(struct device *dev, const char *id); + + +/************************* + ** linux/stmp_device.h ** + *************************/ + +extern int stmp_reset_block(void __iomem *); + + +/******************** + ** linux/regmap.h ** + ********************/ + +struct regmap; + +int regmap_write(struct regmap *map, unsigned int reg, unsigned int val); +int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val); + + +/************************ + ** linux/mfd/syscon.h ** + ************************/ + +struct regmap *syscon_regmap_lookup_by_phandle(struct device_node *np, const char *property); + + +static inline u32 __raw_readl(const volatile void __iomem *addr) +{ + return *(const volatile u32 __force *) addr; +} + +static inline void __raw_writel(u32 b, volatile void __iomem *addr) +{ + *(volatile u32 __force *) addr = b; +} + +struct usb_phy *devm_usb_get_phy_by_phandle(struct device *dev, const char *phandle, u8 index); +struct usb_phy *devm_usb_get_phy_dev(struct device *dev, u8 index); + +extern int usb_add_phy_dev(struct usb_phy *); + + +/************************ + ** linux/tracepoint.h ** + ************************/ + +#define DECLARE_EVENT_CLASS(name, proto, args, tstruct, assign, print) +#define DEFINE_EVENT(template, name, proto, args) + +#define TP_PROTO(args...) args +#define TP_STRUCT__entry(args...) (args) +#define TP_ARGS(args...) (args) +#define TP_printk(fmt, args...) (fmt "\n" args) +#define TP_fast_assign(args...) (args) + + +/******************* + ** Tracing stuff ** + *******************/ + +#define trace_xhci_address_ctx(p1, p2, v) +#define trace_xhci_alloc_dev(p) +#define trace_xhci_alloc_virt_device(p) +#define trace_xhci_configure_endpoint(p) +#define trace_xhci_discover_or_reset_device(p) +#define trace_xhci_free_dev(p) +#define trace_xhci_free_virt_device(p) +#define trace_xhci_get_port_status(p1, p2) +#define trace_xhci_handle_cmd_addr_dev(p) +#define trace_xhci_handle_cmd_config_ep(p) +#define trace_xhci_handle_cmd_disable_slot(p) +#define trace_xhci_handle_cmd_reset_dev(p) +#define trace_xhci_handle_cmd_reset_ep(p) +#define trace_xhci_handle_cmd_set_deq(p) +#define trace_xhci_handle_cmd_set_deq_ep(p) +#define trace_xhci_handle_cmd_stop_ep(p) +#define trace_xhci_handle_command(p1, p2) +#define trace_xhci_handle_event(p1, p2) +#define trace_xhci_handle_port_status(p1, p2) +#define trace_xhci_handle_transfer(p1, p2) +#define trace_xhci_hub_status_data(p1, p2) +#define trace_xhci_inc_deq(p) +#define trace_xhci_inc_enq(p) +#define trace_xhci_queue_trb(p1, p2) +#define trace_xhci_ring_alloc(p) +#define trace_xhci_ring_expansion(p) +#define trace_xhci_ring_free(p) +#define trace_xhci_setup_addressable_virt_device(p) +#define trace_xhci_setup_device(p) +#define trace_xhci_setup_device_slot(p) +#define trace_xhci_stop_device(p1) +#define trace_xhci_urb_dequeue(p) +#define trace_xhci_urb_enqueue(p) +#define trace_xhci_urb_giveback(p) + +static inline void trace_xhci_dbg_init(struct va_format *v) {} +static inline void trace_xhci_dbg_ring_expansion(struct va_format *v) {} +static inline void trace_xhci_dbg_context_change(struct va_format *v) {} +static inline void trace_xhci_dbg_cancel_urb(struct va_format *v) {} +static inline void trace_xhci_dbg_reset_ep(struct va_format *v) {} +static inline void trace_xhci_dbg_quirks(struct va_format *v) {} +static inline void trace_xhci_dbg_address(struct va_format *v) {} + +#define trace_dwc3_readl(v0, v1, v2) +#define trace_dwc3_writel(v0, v1, v2) + +void lx_backtrace(void); + +#include + +#endif /* _LX_EMUL_H_ */ diff --git a/repos/dde_linux/src/drivers/usb_host/main.cc b/repos/dde_linux/src/drivers/usb_host/main.cc new file mode 100644 index 000000000..94f94eb1c --- /dev/null +++ b/repos/dde_linux/src/drivers/usb_host/main.cc @@ -0,0 +1,171 @@ +/* + * \brief Startup USB driver library + * \author Sebastian Sumpf + * \date 2013-02-20 + */ + +/* + * Copyright (C) 2013-2017 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +/* Genode */ +#include +#include +#include + +/* Local */ +#include +#include + +#include +#include +#include +#include +#include +#include +#include + + +using namespace Genode; + +extern "C" int subsys_usb_init(); +extern "C" void module_raw_driver_init(); +extern "C" void start_input_service(void *ep, void *services); + +struct workqueue_struct *system_power_efficient_wq; +struct workqueue_struct *system_wq; +struct workqueue_struct *tasklet_wq; + +void breakpoint() { Genode::log("BREAK"); } + +extern "C" int stdout_write(const char *); + +static void run_linux(void *s) +{ + Services *services = (Services *)s; + + system_power_efficient_wq = alloc_workqueue("system_power_efficient_wq", 0, 0); + system_wq = alloc_workqueue("system_wq", 0, 0); + tasklet_wq = alloc_workqueue("tasklet_wq", 0, 0); + + /* low level interface */ + module_raw_driver_init(); + + /* USB */ + subsys_usb_init(); + + /* host controller */ + platform_hcd_init(services); + + while (true) + Lx::scheduler().current()->block_and_schedule(); +} + + +static void start_usb_driver(Genode::Env &env) +{ + /* initialize USB env */ + Lx_kit::construct_env(env); + + /* sets up backend alloc needed by malloc */ + backend_alloc_init(env, env.ram(), Lx_kit::env().heap()); + + Lx::malloc_init(env, Lx_kit::env().heap()); + + static Services services(env); + + Raw::init(env, services.raw_report_device_list); + + Lx::scheduler(&env); + Lx::timer(&env, &env.ep(), &Lx_kit::env().heap(), &jiffies); + + Lx::Irq::irq(&env.ep(), &Lx_kit::env().heap()); + Lx::Work::work_queue(&Lx_kit::env().heap()); + + static Lx::Task linux(run_linux, &services, "linux", Lx::Task::PRIORITY_0, + Lx::scheduler()); + + Lx::scheduler().schedule(); +} + +namespace Usb_driver { + + using namespace Genode; + + struct Driver_starter { virtual void start_driver() = 0; }; + struct Main; +} + + +struct Usb_driver::Main : Driver_starter +{ + Env &_env; + + /* + * Defer the startup of the USB driver until the first configuration + * becomes available. This is needed in scenarios where the configuration + * is dynamically generated and supplied to the USB driver via the + * report-ROM service. + */ + struct Initial_config_handler + { + Driver_starter &_driver_starter; + + Attached_rom_dataspace _config; + + Signal_handler _config_handler; + + void _handle_config() + { + _config.update(); + + if (_config.xml().type() == "config") + _driver_starter.start_driver(); + } + + Initial_config_handler(Env &env, Driver_starter &driver_starter) + : + _driver_starter(driver_starter), + _config(env, "config"), + _config_handler(env.ep(), *this, &Initial_config_handler::_handle_config) + { + _config.sigh(_config_handler); + _handle_config(); + } + }; + + void _handle_start() + { + if (_initial_config_handler.constructed()) { + _initial_config_handler.destruct(); + start_usb_driver(_env); + } + } + + Signal_handler
_start_handler { + _env.ep(), *this, &Main::_handle_start }; + + Reconstructible _initial_config_handler { _env, *this }; + + /* + * Called from 'Initial_config_handler' + */ + void start_driver() override + { + Signal_transmitter(_start_handler).submit(); + } + + Main(Env &env) : _env(env) { } +}; + + +void Component::construct(Genode::Env &env) +{ + /* XXX execute constructors of global statics */ + env.exec_static_constructors(); + + static Usb_driver::Main main(env); +} diff --git a/repos/dde_linux/src/drivers/usb_host/platform.h b/repos/dde_linux/src/drivers/usb_host/platform.h new file mode 100644 index 000000000..f65730191 --- /dev/null +++ b/repos/dde_linux/src/drivers/usb_host/platform.h @@ -0,0 +1,50 @@ +/* + * \brief Platform specific definitions + * \author Sebastian Sumpf + * \date 2012-07-06 + * + * These functions have to be implemented on all supported platforms. + */ + +/* + * Copyright (C) 2012-2017 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +#ifndef _PLATFORM_H_ +#define _PLATFORM_H_ + +#include +#include +#include + +#include + +struct Services +{ + Genode::Env &env; + + /* report generation */ + bool raw_report_device_list = false; + + Services(Genode::Env &env) : env(env) + { + using namespace Genode; + + Genode::Xml_node config_node = Lx_kit::env().config_rom().xml(); + + try { + Genode::Xml_node node_report = config_node.sub_node("report"); + raw_report_device_list = node_report.attribute_value("devices", false); + } catch (...) { } + } +}; + +void backend_alloc_init(Genode::Env &env, Genode::Ram_session &ram, Genode::Allocator &alloc); + +void platform_hcd_init(Services *services); +Genode::Irq_session_capability platform_irq_activate(int irq); + +#endif /* _PLATFORM_H_ */ diff --git a/repos/dde_linux/src/drivers/usb_host/raw.cc b/repos/dde_linux/src/drivers/usb_host/raw.cc new file mode 100644 index 000000000..f6f48bee2 --- /dev/null +++ b/repos/dde_linux/src/drivers/usb_host/raw.cc @@ -0,0 +1,1135 @@ +/* + * \brief Server side USB session implementation + * \author Sebastian Sumpf + * \date 2014-12-08 + */ + +/* + * Copyright (C) 2014-2017 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include "raw.h" +#include +#include + +#include +#include + +using namespace Genode; + +extern "C" int usb_set_configuration(struct usb_device *dev, int configuration); + +constexpr bool verbose_raw = false; + + +namespace Usb { + class Session_component; + class Root; + class Worker; + class Cleaner; +} + +/** + * Keep track of all registered USB devices (via raw driver) + */ +struct Device : List::Element +{ + usb_device *udev; + + static List *list() + { + static List _l; + return &_l; + } + + static Device * device_product(uint16_t vendor, uint16_t product) + { + for (Device *d = list()->first(); d; d = d->next()) { + if (d->udev->descriptor.idVendor == vendor && d->udev->descriptor.idProduct == product) + return d; + } + + return nullptr; + } + + + static Device * device_bus(long bus, long dev) + { + for (Device *d = list()->first(); d; d = d->next()) { + if (d->udev->bus->busnum == bus && d->udev->devnum == dev) + return d; + } + + return nullptr; + } + + static Device * device_class(long class_, Session_label label) + { + for (Device *d = list()->first(); d; d = d->next()) { + long c = d->interface(0)->cur_altsetting->desc.bInterfaceClass; + if (class_ == c && label == d->label()) + return d; + } + + return nullptr; + } + + static void report_device_list(); + + Device(usb_device *udev) : udev(udev) + { + list()->insert(this); + report_device_list(); + } + + ~Device() + { + list()->remove(this); + report_device_list(); + } + + usb_interface *interface(unsigned index) + { + if (!udev || !udev->actconfig) + return nullptr; + + if (index >= udev->actconfig->desc.bNumInterfaces) + return nullptr; + + usb_interface *iface = udev->actconfig->interface[index]; + return iface; + } + + usb_host_endpoint *endpoint(usb_interface *iface, unsigned alt_setting, + unsigned endpoint_num) + { + return &iface->altsetting[alt_setting].endpoint[endpoint_num]; + } + + Session_label label() { + return Session_label("usb-", udev->bus->busnum, "-", udev->devnum); } +}; + + +/** + * Handle packet stream request, this way the entrypoint always returns to it's + * server loop + */ +class Usb::Worker : public Genode::Weak_object +{ + private: + + completion _packet_avail; + + Session::Tx::Sink *_sink; + Device *_device = nullptr; + Signal_context_capability _sigh_ready; + Lx::Task *_task = nullptr; + unsigned _p_in_flight = 0; + bool _device_ready = false; + + void _ack_packet(Packet_descriptor &p) + { + _sink->acknowledge_packet(p); + _p_in_flight--; + } + + /** + * Retrieve string descriptor at index given in packet + */ + void _retrieve_string(Packet_descriptor &p) + { + char *buffer = _sink->packet_content(p); + int length; + + if ((length = usb_string(_device->udev, p.string.index, buffer, p.size())) < 0) { + warning("Could not read string descriptor index: ", (unsigned)p.string.index); + p.string.length = 0; + } else { + /* returned length is in bytes (char) */ + p.string.length = length / 2; + p.succeded = true; + } + } + + /** + * Read control transfer + */ + void _ctrl_in(Packet_descriptor &p) + { + void *buf = kmalloc(4096, GFP_NOIO); + + int err = usb_control_msg(_device->udev, usb_rcvctrlpipe(_device->udev, 0), + p.control.request, p.control.request_type, + p.control.value, p.control.index, buf, + p.size(), p.control.timeout); + + if (err > 0 && p.size()) + Genode::memcpy(_sink->packet_content(p), buf, err); + + kfree(buf); + + p.control.actual_size = err; + + p.succeded = (err < 0 && err != -EPIPE) ? false : true; + } + + /** + * Write control transfer + */ + void _ctrl_out(Packet_descriptor &p) + { + void *buf = kmalloc(4096, GFP_NOIO); + + if (p.size()) + Genode::memcpy(buf, _sink->packet_content(p), p.size()); + + int err = usb_control_msg(_device->udev, usb_sndctrlpipe(_device->udev, 0), + p.control.request, p.control.request_type, + p.control.value, p.control.index, buf, p.size(), + p.control.timeout); + if (err >= 0 || err== -EPIPE) { + p.control.actual_size = err; + p.succeded = true; + } + + if (err >= 0 + && p.control.request == USB_REQ_CLEAR_FEATURE + && p.control.value == USB_ENDPOINT_HALT) { + usb_reset_endpoint(_device->udev, p.control.index); + } + kfree(buf); + } + + /** + * Asynchronous transfer helpers + */ + struct Complete_data + { + Weak_ptr worker; + Packet_descriptor packet; + + Complete_data(Weak_ptr &w, Packet_descriptor &p) + : worker(w), packet(p) { } + }; + + Complete_data * alloc_complete_data(Packet_descriptor &p) + { + void * data = kmalloc(sizeof(Complete_data), GFP_KERNEL); + construct_at(data, this->weak_ptr(), p); + return reinterpret_cast(data); + } + + static void free_complete_data(Complete_data *data) + { + data->packet.~Packet_descriptor(); + data->worker.~Weak_ptr(); + kfree (data); + } + + void _async_finish(Packet_descriptor &p, urb *urb, bool read) + { + if (urb->status == 0) { + p.transfer.actual_size = urb->actual_length; + p.succeded = true; + + if (read) + Genode::memcpy(_sink->packet_content(p), urb->transfer_buffer, + urb->actual_length); + } + + if (urb->status == -EPIPE) { + p.error = Packet_descriptor::STALL_ERROR; + } + + _ack_packet(p); + } + + static void _async_complete(urb *urb) + { + Complete_data *data = (Complete_data *)urb->context; + + { + Locked_ptr worker(data->worker); + + if (worker.valid()) + worker->_async_finish(data->packet, urb, + !!(data->packet.transfer.ep & USB_DIR_IN)); + } + + free_complete_data(data); + dma_free(urb->transfer_buffer); + usb_free_urb(urb); + } + + /** + * Bulk transfer + */ + bool _bulk(Packet_descriptor &p, bool read) + { + unsigned pipe; + void *buf = dma_malloc(p.size()); + + if (read) + pipe = usb_rcvbulkpipe(_device->udev, p.transfer.ep); + else { + pipe = usb_sndbulkpipe(_device->udev, p.transfer.ep); + Genode::memcpy(buf, _sink->packet_content(p), p.size()); + } + + urb *bulk_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!bulk_urb) { + error("Failed to allocate bulk URB"); + dma_free(buf); + p.error = Usb::Packet_descriptor::SUBMIT_ERROR; + return false; + } + + Complete_data *data = alloc_complete_data(p); + + usb_fill_bulk_urb(bulk_urb, _device->udev, pipe, buf, p.size(), + _async_complete, data); + + int ret = usb_submit_urb(bulk_urb, GFP_KERNEL); + if (ret != 0) { + error("Failed to submit URB, error: ", ret); + p.error = Usb::Packet_descriptor::SUBMIT_ERROR; + + free_complete_data(data); + usb_free_urb(bulk_urb); + dma_free(buf); + return false; + } + + return true; + } + + /** + * IRQ transfer + */ + bool _irq(Packet_descriptor &p, bool read) + { + unsigned pipe; + void *buf = dma_malloc(p.size()); + + if (read) + pipe = usb_rcvintpipe(_device->udev, p.transfer.ep); + else { + pipe = usb_sndintpipe(_device->udev, p.transfer.ep); + Genode::memcpy(buf, _sink->packet_content(p), p.size()); + } + + urb *irq_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!irq_urb) { + error("Failed to allocate interrupt URB"); + dma_free(buf); + p.error = Usb::Packet_descriptor::SUBMIT_ERROR; + return false; + } + + Complete_data *data = alloc_complete_data(p); + + int polling_interval; + + if (p.transfer.polling_interval == Usb::Packet_descriptor::DEFAULT_POLLING_INTERVAL) { + + usb_host_endpoint *ep = read ? _device->udev->ep_in[p.transfer.ep & 0x0f] + : _device->udev->ep_out[p.transfer.ep & 0x0f]; + polling_interval = ep->desc.bInterval; + + } else + polling_interval = p.transfer.polling_interval; + + usb_fill_int_urb(irq_urb, _device->udev, pipe, buf, p.size(), + _async_complete, data, polling_interval); + + int ret = usb_submit_urb(irq_urb, GFP_KERNEL); + if (ret != 0) { + error("Failed to submit URB, error: ", ret); + p.error = Usb::Packet_descriptor::SUBMIT_ERROR; + + free_complete_data(data); + usb_free_urb(irq_urb); + dma_free(buf); + return false; + } + + return true; + } + + /** + * Isochronous transfer + */ + bool _isoc(Packet_descriptor &p, bool read) + { + unsigned pipe; + usb_host_endpoint *ep; + void *buf = dma_malloc(p.size()); + + if (read) { + pipe = usb_rcvisocpipe(_device->udev, p.transfer.ep); + ep = _device->udev->ep_in[p.transfer.ep & 0x0f]; + } + else { + pipe = usb_sndisocpipe(_device->udev, p.transfer.ep); + ep = _device->udev->ep_out[p.transfer.ep & 0x0f]; + Genode::memcpy(buf, _sink->packet_content(p), p.size()); + } + + urb *urb = usb_alloc_urb(p.transfer.number_of_packets, GFP_KERNEL); + if (!urb) { + error("Failed to allocate isochronous URB"); + dma_free(buf); + p.error = Usb::Packet_descriptor::SUBMIT_ERROR; + return false; + } + + Complete_data *data = alloc_complete_data(p); + urb->dev = _device->udev; + urb->pipe = pipe; + urb->start_frame = -1; + urb->stream_id = 0; + urb->transfer_buffer = buf; + urb->transfer_buffer_length = p.size(); + urb->number_of_packets = p.transfer.number_of_packets; + urb->interval = 1 << min(15, ep->desc.bInterval - 1); + urb->context = (void *)data; + urb->transfer_flags = URB_ISO_ASAP | (read ? URB_DIR_IN : URB_DIR_OUT); + urb->complete = _async_complete; + + unsigned offset = 0; + for (int i = 0; i < p.transfer.number_of_packets; i++) { + urb->iso_frame_desc[i].offset = offset; + urb->iso_frame_desc[i].length = p.transfer.packet_size[i]; + offset += p.transfer.packet_size[i]; + } + + int ret = usb_submit_urb(urb, GFP_KERNEL); + if (ret == 0) + return true; + + error("Failed to submit URB, error: ", ret); + p.error = Usb::Packet_descriptor::SUBMIT_ERROR; + + free_complete_data(data); + usb_free_urb(urb); + dma_free(buf); + return false; + } + + /** + * Change alternate settings for device + */ + void _alt_setting(Packet_descriptor &p) + { + int err = usb_set_interface(_device->udev, p.interface.number, + p.interface.alt_setting); + if (!err) + p.succeded = true; + } + + /** + * Set configuration + */ + void _config(Packet_descriptor &p) + { + usb_host_config *config = _device->udev->actconfig; + + if (!config) + return; + + for (unsigned i = 0; i < config->desc.bNumInterfaces; i++) { + if (usb_interface_claimed(config->interface[i])) { + error("There are interfaces claimed, won't set configuration"); + return; + } + } + + int err = usb_set_configuration(_device->udev, p.number); + + if (!err) + p.succeded = true; + } + + /** + * Release interface + */ + void _release_interface(Packet_descriptor &p) + { + usb_interface *iface = _device->interface(p.number); + + if (!iface) + return; + + usb_driver_release_interface(&raw_intf_driver, iface); + p.succeded = true; + } + + /** + * Dispatch incoming packet types + */ + void _dispatch() + { + /* + * Get packets until there are no more free ack slots or avaiable + * packets + */ + while (_p_in_flight < _sink->ack_slots_free() && _sink->packet_avail()) + { + Packet_descriptor p = _sink->get_packet(); + + if (verbose_raw) + log("PACKET: ", (unsigned)p.type, " first value: ", Hex(p.number)); + + _p_in_flight++; + + if (!_device || !_device->udev || + _device->udev->state == USB_STATE_NOTATTACHED) { + _ack_packet(p); + continue; + } + + switch (p.type) { + + case Packet_descriptor::STRING: + _retrieve_string(p); + break; + + case Packet_descriptor::CTRL: + if (p.control.request_type & Usb::ENDPOINT_IN) + _ctrl_in(p); + else + _ctrl_out(p); + break; + + case Packet_descriptor::BULK: + if (_bulk(p, p.read_transfer())) + continue; + break; + + case Packet_descriptor::IRQ: + if (_irq(p, p.read_transfer())) + continue; + break; + + case Packet_descriptor::ISOC: + if (_isoc(p, p.read_transfer())) + continue; + break; + + case Packet_descriptor::ALT_SETTING: + _alt_setting(p); + break; + + case Packet_descriptor::CONFIG: + _config(p); + break; + + case Packet_descriptor::RELEASE_IF: + _release_interface(p); + break; + } + + _ack_packet(p); + } + } + + void _wait_for_device() + { + wait_queue_head_t wait; + _wait_event(wait, _device); + _wait_event(wait, _device->udev->actconfig); + + if (_sigh_ready.valid()) + Signal_transmitter(_sigh_ready).submit(1); + + _device_ready = true; + } + + /** + * Wait for packets + */ + void _wait() + { + /* wait for device to become ready */ + init_completion(&_packet_avail); + _wait_for_device(); + + while (true) { + wait_for_completion(&_packet_avail); + _dispatch(); + } + } + + public: + + static void run(void *worker) + { + Worker *w = static_cast(worker); + w->_wait(); + } + + Worker(Session::Tx::Sink *sink) + : _sink(sink) + { } + + ~Worker() + { + Weak_object::lock_for_destruction(); + } + + void start() + { + if (!_task) { + _task = new (Lx::Malloc::mem()) Lx::Task(run, this, "raw_worker", + Lx::Task::PRIORITY_2, + Lx::scheduler()); + if (!Lx::scheduler().active()) { + Lx::scheduler().schedule(); + } + } + } + + void stop() + { + if (_task) { + Lx::scheduler().remove(_task); + destroy(Lx::Malloc::mem(), _task); + _task = nullptr; + } + } + + void packet_avail() { ::complete(&_packet_avail); } + + void device(Device *device, Signal_context_capability sigh_ready = Signal_context_capability()) + { + _device = device; + _sigh_ready = sigh_ready; + } + + bool device_ready() { return _device_ready; } +}; + + +struct Interface : List<::Interface>::Element +{ + usb_interface *iface; + + Interface(usb_interface *iface) : iface(iface) { } +}; + + +/** + * Asynchronous USB-interface release + */ +class Usb::Cleaner : List<::Interface> +{ + private: + + static void _run(void *c) + { + Cleaner *cleaner = (Cleaner *)c; + + while (true) { + cleaner->_task.block_and_schedule(); + + while (::Interface *interface = cleaner->first()) { + usb_driver_release_interface(&raw_intf_driver, interface->iface); + cleaner->remove(interface); + destroy(Lx::Malloc::mem(), interface); + } + } + } + + Lx::Task _task { _run, this, "raw_cleaner", Lx::Task::PRIORITY_2, + Lx::scheduler() }; + + public: + + void schedule_release(usb_interface *iface) + { + ::Interface *interface = new(Lx::Malloc::mem()) ::Interface(iface); + insert(interface); + _task.unblock(); + Lx::scheduler().schedule(); + } +}; + + +/***************** + ** USB session ** + *****************/ + +class Usb::Session_component : public Session_rpc_object, + public List::Element +{ + private: + + Session_label _label; + Genode::Entrypoint &_ep; + unsigned long _vendor; + unsigned long _product; + long _bus = 0; + long _dev = 0; + long _class = 0; + Device *_device = nullptr; + Signal_context_capability _sigh_state_change; + Io_signal_handler _packet_avail; + Io_signal_handler _ready_ack; + Worker _worker; + Ram_dataspace_capability _tx_ds; + Usb::Cleaner &_cleaner; + + + void _signal_state_change() + { + if (_sigh_state_change.valid()) + Signal_transmitter(_sigh_state_change).submit(1); + } + + void _receive() + { + _worker.packet_avail(); + Lx::scheduler().schedule(); + } + + public: + + enum State { + DEVICE_ADD, + DEVICE_REMOVE, + }; + + Session_component(Session_label label, + Genode::Ram_dataspace_capability tx_ds, + Genode::Entrypoint &ep, + Genode::Region_map &rm, + unsigned long vendor, unsigned long product, + long bus, long dev, long class_, + Usb::Cleaner &cleaner) + : Session_rpc_object(tx_ds, ep.rpc_ep(), rm), + _label(label), _ep(ep), _vendor(vendor), _product(product), + _bus(bus), _dev(dev), _class(class_), + _packet_avail(ep, *this, &Session_component::_receive), + _ready_ack(ep, *this, &Session_component::_receive), + _worker(sink()), _tx_ds(tx_ds), _cleaner(cleaner) + { + Device *device; + if (bus && dev) { + device = Device::device_bus(bus, dev); + } else if (vendor && product) { + device = Device::device_product(_vendor, _product); + } else + device = Device::device_class(_class, _label); + if (device) { + state_change(DEVICE_ADD, device); + } + + /* register signal handlers */ + _tx.sigh_packet_avail(_packet_avail); + } + + ~Session_component() + { + /* release claimed interfaces */ + if (_device && _device->udev && _device->udev->actconfig) { + unsigned const num = _device->udev->actconfig->desc.bNumInterfaces; + for (unsigned i = 0; i < num; i++) + release_interface(i); + } + + _worker.stop(); + } + + /*********************** + ** Session interface ** + ***********************/ + + bool plugged() { return _device != nullptr; } + + void claim_interface(unsigned interface_num) override + { + if (!_device) + throw Device_not_found(); + + usb_interface *iface = _device->interface(interface_num); + if (!iface) + throw Interface_not_found(); + + if (usb_driver_claim_interface(&raw_intf_driver, iface, nullptr)) + throw Interface_already_claimed(); + } + + void release_interface(unsigned interface_num) override + { + if (!_device) + throw Device_not_found(); + + usb_interface *iface = _device->interface(interface_num); + if (!iface) + throw Interface_not_found(); + + _cleaner.schedule_release(iface); + } + + void config_descriptor(Device_descriptor *device_descr, + Config_descriptor *config_descr) override + { + if (!_device) + throw Device_not_found(); + + Genode::memcpy(device_descr, &_device->udev->descriptor, sizeof(usb_device_descriptor)); + + if (_device->udev->actconfig) + Genode::memcpy(config_descr, &_device->udev->actconfig->desc, sizeof(usb_config_descriptor)); + else + Genode::memset(config_descr, 0, sizeof(usb_config_descriptor)); + + device_descr->num = _device->udev->devnum; + device_descr->speed = _device->udev->speed; + } + + unsigned alt_settings(unsigned index) override + { + if (!_device) + throw Device_not_found(); + + usb_interface *iface = _device->interface(index); + if (!iface) + throw Interface_not_found(); + + return iface->num_altsetting; + } + + void interface_descriptor(unsigned index, unsigned alt_setting, + Interface_descriptor *interface_descr) override + { + if (!_device) + throw Device_not_found(); + + usb_interface *iface = _device->interface(index); + if (!iface) + throw Interface_not_found(); + + Genode::memcpy(interface_descr, &iface->altsetting[alt_setting].desc, + sizeof(usb_interface_descriptor)); + + if (&iface->altsetting[alt_setting] == iface->cur_altsetting) + interface_descr->active = true; + } + + void endpoint_descriptor(unsigned interface_num, + unsigned alt_setting, + unsigned endpoint_num, + Endpoint_descriptor *endpoint_descr) override + { + if (!_device || !_device->udev) + throw Device_not_found(); + + usb_interface *iface = usb_ifnum_to_if(_device->udev, interface_num); + if (!iface) + throw Interface_not_found(); + + Genode::memcpy(endpoint_descr, &_device->endpoint(iface, alt_setting, + endpoint_num)->desc, sizeof(usb_endpoint_descriptor)); + } + + /********************* + ** Local interface ** + *********************/ + + bool session_device(Device *device) + { + usb_device_descriptor *descr = &device->udev->descriptor; + usb_interface *iface = device->interface(0); + + return (descr->idVendor == _vendor && descr->idProduct == _product) + || (_bus && _dev && _bus == device->udev->bus->busnum && + _dev == device->udev->devnum) + || (iface && iface->cur_altsetting && + _class == iface->cur_altsetting->desc.bInterfaceClass && + _label == device->label())? true : false; + } + + bool state_change(State state, Device *device) + { + switch (state) { + case DEVICE_ADD: + if (!session_device(device)) + return false; + + if (_device) + warning("Device type already present (vendor: ", + Hex(device->udev->descriptor.idVendor), + " product: ", Hex(device->udev->descriptor.idProduct), + ") Overwrite!"); + + _device = device; + _worker.device(_device, _sigh_state_change); + _worker.start(); + return true; + + case DEVICE_REMOVE: + if (!session_device(device)) + return false; + _device = nullptr; + _worker.stop(); + _signal_state_change(); + return true; + } + + return false; + } + + void sigh_state_change(Signal_context_capability sigh) + { + _sigh_state_change = sigh; + + if (_worker.device_ready()) + Signal_transmitter(_sigh_state_change).submit(1); + } + + Ram_dataspace_capability tx_ds() { return _tx_ds; } +}; + + +struct Session : public List +{ + static Session *list() + { + static Session _l; + return &_l; + } + + void state_change(Usb::Session_component::State state, Device *device) + { + for (Usb::Session_component *session = list()->first(); session; session = session->next()) + if (session->state_change(state, device)) + return; + } +}; + + +class Usb::Root : public Genode::Root_component +{ + private: + + Genode::Env &_env; + + Genode::Signal_handler _config_handler = { + _env.ep(), *this, &Usb::Root::_handle_config }; + + Genode::Reporter _config_reporter { _env, "config" }; + + Genode::Reporter _device_list_reporter { + _env, "devices", "devices", 512*1024 }; + + Usb::Cleaner _cleaner; + + void _handle_config() + { + Lx_kit::env().config_rom().update(); + + Genode::Xml_node config = Lx_kit::env().config_rom().xml(); + + if (!_config_reporter.enabled()) + _config_reporter.enabled(true); + + bool const uhci = config.attribute_value("uhci", false); + bool const ehci = config.attribute_value("ehci", false); + bool const xhci = config.attribute_value("xhci", false); + bool const ohci = config.attribute_value("ohci", false); + + Genode::Reporter::Xml_generator xml(_config_reporter, [&] { + if (uhci) xml.attribute("uhci", "yes"); + if (ehci) xml.attribute("ehci", "yes"); + if (xhci) xml.attribute("xhci", "yes"); + if (ohci) xml.attribute("ohci", "yes"); + + xml.append(config.content_base(), config.content_size()); + }); + } + + protected: + + Session_component *_create_session(const char *args) + { + using namespace Genode; + using Genode::size_t; + + Session_label const label = label_from_args(args); + try { + Xml_node config_node = Lx_kit::env().config_rom().xml(); + Genode::Session_policy policy(label, config_node); + + size_t ram_quota = Arg_string::find_arg(args, "ram_quota" ).ulong_value(0); + size_t tx_buf_size = Arg_string::find_arg(args, "tx_buf_size").ulong_value(0); + + unsigned long vendor = policy.attribute_value("vendor_id", 0); + unsigned long product = policy.attribute_value("product_id", 0); + unsigned long bus = policy.attribute_value("bus", 0); + unsigned long dev = policy.attribute_value("dev", 0); + unsigned long class_ = policy.attribute_value("class", 0); + + /* check session quota */ + size_t session_size = max(4096, sizeof(Session_component)); + if (ram_quota < session_size) + throw Insufficient_ram_quota(); + + if (tx_buf_size > ram_quota - session_size) { + error("Insufficient 'ram_quota',got ", ram_quota, " need ", + tx_buf_size + session_size); + throw Insufficient_ram_quota(); + } + + Ram_dataspace_capability tx_ds = _env.ram().alloc(tx_buf_size); + Session_component *session = new (md_alloc()) + Session_component(label.last_element(), tx_ds, _env.ep(), + _env.rm(), vendor, product, bus, dev, + class_, _cleaner); + ::Session::list()->insert(session); + return session; + } + catch (Genode::Session_policy::No_policy_defined) { + error("Invalid session request, no matching policy for '", + label.string(), "'"); + throw Genode::Service_denied(); + } + } + + void _destroy_session(Session_component *session) + { + Ram_dataspace_capability tx_ds = session->tx_ds(); + + ::Session::list()->remove(session); + Genode::Root_component::_destroy_session(session); + + _env.ram().free(tx_ds); + } + + public: + + Root(Genode::Env &env, + Genode::Allocator &md_alloc, + bool report_device_list) + : Genode::Root_component(env.ep(), md_alloc), + _env(env) + { + Lx_kit::env().config_rom().sigh(_config_handler); + _device_list_reporter.enabled(report_device_list); + } + + Genode::Reporter &device_list_reporter() + { + return _device_list_reporter; + } +}; + + +static Genode::Constructible root; + + +void Raw::init(Genode::Env &env, bool report_device_list) +{ + root.construct(env, Lx::Malloc::mem(), report_device_list); + env.parent().announce(env.ep().manage(*root)); +} + + +void Device::report_device_list() +{ + if (!root->device_list_reporter().enabled()) + return; + + Genode::Reporter::Xml_generator xml(root->device_list_reporter(), [&] () + { + + for (Device *d = list()->first(); d; d = d->next()) { + xml.node("device", [&] () + { + char buf[16]; + + unsigned const bus = d->udev->bus->busnum; + unsigned const dev = d->udev->devnum; + + xml.attribute("label", d->label().string()); + + Genode::snprintf(buf, sizeof(buf), "0x%4x", + d->udev->descriptor.idVendor); + xml.attribute("vendor_id", buf); + + Genode::snprintf(buf, sizeof(buf), "0x%4x", + d->udev->descriptor.idProduct); + xml.attribute("product_id", buf); + + Genode::snprintf(buf, sizeof(buf), "0x%4x", bus); + xml.attribute("bus", buf); + + Genode::snprintf(buf, sizeof(buf), "0x%4x", dev); + xml.attribute("dev", buf); + + usb_interface *iface = d->interface(0); + Genode::snprintf(buf, sizeof(buf), "0x%02x", + iface->cur_altsetting->desc.bInterfaceClass); + xml.attribute("class", buf); + }); + } + }); +} + +/***************** + ** C interface ** + *****************/ + +int raw_notify(struct notifier_block *nb, unsigned long action, void *data) +{ + struct usb_device *udev = (struct usb_device*)data; + + if (verbose_raw) + log("RAW: ",action == USB_DEVICE_ADD ? "Add" : "Remove", + " vendor: ", Hex(udev->descriptor.idVendor), + " product: ", Hex(udev->descriptor.idProduct)); + + + switch (action) { + + case USB_DEVICE_ADD: + { + ::Session::list()->state_change(Usb::Session_component::DEVICE_ADD, + new (Lx::Malloc::mem()) Device(udev)); + break; + } + + case USB_DEVICE_REMOVE: + { + Device *dev = Device::device_bus(udev->bus->busnum, + udev->devnum); + if (dev) { + ::Session::list()->state_change(Usb::Session_component::DEVICE_REMOVE, dev); + destroy(Lx::Malloc::mem(), dev); + } + break; + } + + case USB_BUS_ADD: + break; + + case USB_BUS_REMOVE: + break; + } + + return NOTIFY_OK; +} diff --git a/repos/dde_linux/src/drivers/usb_host/raw.h b/repos/dde_linux/src/drivers/usb_host/raw.h new file mode 100644 index 000000000..672717236 --- /dev/null +++ b/repos/dde_linux/src/drivers/usb_host/raw.h @@ -0,0 +1,12 @@ +#ifndef _RAW_H_ +#define _RAW_H_ + +struct usb_device; +struct usb_driver; + +extern struct usb_device_driver raw_driver; +extern struct usb_driver raw_intf_driver; + +int raw_notify(struct notifier_block *nb, unsigned long action, void *data); + +#endif /* _RAW_H_ */ diff --git a/repos/dde_linux/src/drivers/usb_host/raw_driver.c b/repos/dde_linux/src/drivers/usb_host/raw_driver.c new file mode 100644 index 000000000..5d3b566a4 --- /dev/null +++ b/repos/dde_linux/src/drivers/usb_host/raw_driver.c @@ -0,0 +1,94 @@ +/* + * \brief Low level USB access driver + * \author Sebastian Sumpf + * \date 2014-11-11 + */ + +/* + * Copyright (C) 2014-2017 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +#include +#include "raw.h" + +static int raw_probe(struct usb_device *udev) +{ + printk("RAW: vendor: %x product: %x dev %p\n", + udev->descriptor.idVendor, udev->descriptor.idProduct, udev); + + return -ENODEV; +} + +static void raw_disconnect(struct usb_device *udev) +{ + printk("driver disconnect called\n"); +} + + +struct usb_device_driver raw_driver = +{ + .name = "raw", + .probe = raw_probe, + .disconnect = raw_disconnect, + .supports_autosuspend = 0, +}; + + +static int raw_intf_probe(struct usb_interface *intf, + struct usb_device_id const *id) +{ + struct usb_device *udev = interface_to_usbdev(intf); + + printk("RAW_INTF: vendor: %04x product: %04x\n", udev->descriptor.idVendor, + udev->descriptor.idProduct); + + return -ENODEV; +} + +void raw_intf_disconnect(struct usb_interface *intf) { } + +static const struct usb_device_id raw_intf_id_table[] = { + { .driver_info = 1 } +}; + + +struct usb_driver raw_intf_driver = +{ + .name = "rawintf", + .probe = raw_intf_probe, + .disconnect = raw_intf_disconnect, + .supports_autosuspend = 0, +}; + + +struct notifier_block usb_nb = +{ + .notifier_call = raw_notify +}; + + +static int raw_driver_init(void) +{ + int err; + + if ((err = usb_register_device_driver(&raw_driver, THIS_MODULE))) + return err; + + printk("RAW: driver registered\n"); + + if ((err = usb_register(&raw_intf_driver))) + return err; + + printk("RAW: interface driver registered\n"); + + usb_register_notify(&usb_nb); + + printk("RAW: notify function registered\n"); + + return 0; +} + +module_init(raw_driver_init); diff --git a/repos/dde_linux/src/drivers/usb_host/signal.h b/repos/dde_linux/src/drivers/usb_host/signal.h new file mode 100644 index 000000000..632aca883 --- /dev/null +++ b/repos/dde_linux/src/drivers/usb_host/signal.h @@ -0,0 +1,52 @@ +/* + * \brief Main-signal receiver and signal-helper functions + * \author Sebastian Sumpf + * \date 2012-05-23 + */ + +/* + * Copyright (C) 2012-2017 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +#ifndef _SIGNAL_H_ +#define _SIGNAL_H_ + +#include + +#include + +static bool const verbose = false; + +/** + * Helper that holds sender and entrypoint + */ +class Signal_helper +{ + private: + + Genode::Env &_env; + Genode::Signal_transmitter _sender; + + public: + + Signal_helper(Genode::Env &env) : _env(env) { } + + Genode::Entrypoint &ep() { return _env.ep(); } + Genode::Signal_transmitter &sender() { return _sender; } + Genode::Parent &parent() { return _env.parent(); } + Genode::Env &env() { return _env; } + Genode::Ram_session &ram() { return _env.ram(); } + Genode::Region_map &rm() { return _env.rm(); } +}; + + +namespace Raw +{ + void init(Genode::Env &env, bool report_device_list); +} + + +#endif /* _SIGNAL_H_ */ diff --git a/repos/dde_linux/src/drivers/usb_host/spec/arm/platform.cc b/repos/dde_linux/src/drivers/usb_host/spec/arm/platform.cc new file mode 100644 index 000000000..b49ca42f5 --- /dev/null +++ b/repos/dde_linux/src/drivers/usb_host/spec/arm/platform.cc @@ -0,0 +1,87 @@ +/* + * \brief ARM specific implemenations used on all SOCs + * \author Sebastian Sumpf + * \date 2016-04-25 + */ + +/* + * Copyright (C) 2016-2017 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +#include +#include + +#include + +#include +#include +#include + + +/**************************** + ** lx_kit/backend_alloc.h ** + ****************************/ + +void backend_alloc_init(Genode::Env&, Genode::Ram_session&, + Genode::Allocator&) +{ + /* intentionally left blank */ +} + + +Genode::Ram_dataspace_capability +Lx::backend_alloc(Genode::addr_t size, Genode::Cache_attribute cached) { + return Lx_kit::env().env().ram().alloc(size, cached); } + + +void Lx::backend_free(Genode::Ram_dataspace_capability cap) { + return Lx_kit::env().env().ram().free(cap); } + + +/*********************** + ** linux/interrupt.h ** + ***********************/ + +extern "C" int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, + const char *name, void *dev) +{ + Lx::Irq::irq().request_irq(Platform::Device::create(Lx_kit::env().env(), irq), handler, dev); + + return 0; +} + + +int devm_request_irq(struct device *dev, unsigned int irq, irq_handler_t handler, unsigned long irqflags, const char *devname, void *dev_id) +{ + Lx::Irq::irq().request_irq(Platform::Device::create(Lx_kit::env().env(), irq), handler, dev_id); + return 0; +} + + +/********************** + ** asm-generic/io.h ** + **********************/ + +void *_ioremap(phys_addr_t phys_addr, unsigned long size, int wc) +{ + try { + Genode::Attached_io_mem_dataspace *ds = + new(Lx::Malloc::mem()) + Genode::Attached_io_mem_dataspace(Lx_kit::env().env(), phys_addr, size, !!wc); + return ds->local_addr(); + } catch (...) { + panic("Failed to request I/O memory: [%lx,%lx)", phys_addr, phys_addr + size); + return 0; + } +} + + +void *ioremap(phys_addr_t offset, unsigned long size) +{ + return _ioremap(offset, size, 0); +} + + diff --git a/repos/dde_linux/src/drivers/usb_host/spec/arm/platform_device/platform_device.h b/repos/dde_linux/src/drivers/usb_host/spec/arm/platform_device/platform_device.h new file mode 100644 index 000000000..bce54ace6 --- /dev/null +++ b/repos/dde_linux/src/drivers/usb_host/spec/arm/platform_device/platform_device.h @@ -0,0 +1,81 @@ +/* + * \brief Platform_device implementation for ARM + * \author Sebastian Sumpf + * \date 2016-04-25 + * + * Note: Throw away when there exists a plaform device implementation for ARM + * in generic code + */ + +/* + * Copyright (C) 2016-2017 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +#ifndef _ARM__PLATFORM_DEVICE__PLATFORM_DEVICE_H_ +#define _ARM__PLATFORM_DEVICE__PLATFORM_DEVICE_H_ + + +#include +#include +#include + +#include +#include + +#include +#include +#include + + +namespace Platform { struct Device; } + +struct Platform::Device : Platform::Abstract_device, Genode::List::Element +{ + Genode::Env &env; + + unsigned irq_num; + Genode::Constructible irq_connection; + + Device(Genode::Env &env, unsigned irq) : env(env), irq_num(irq) { } + + unsigned vendor_id() { return ~0U; } + unsigned device_id() { return ~0U; } + + Genode::Irq_session_capability irq(Genode::uint8_t) override + { + irq_connection.construct(env, irq_num); + return irq_connection->cap(); + } + + Genode::Io_mem_session_capability io_mem(Genode::uint8_t, + Genode::Cache_attribute, + Genode::addr_t, Genode::size_t) override + { + lx_printf("%s: not implemented\n", __PRETTY_FUNCTION__); + return Genode::Io_mem_session_capability(); + } + + static Genode::List &list() + { + static Genode::List l; + return l; + } + + static Device &create(Genode::Env &env, unsigned irq_num) + { + Device *d; + for (d = list().first(); d; d = d->next()) + if (d->irq_num == irq_num) + return *d; + + d = new (Lx::Malloc::mem()) Device(env, irq_num); + list().insert(d); + + return *d; + } +}; + +#endif /* _ARM__PLATFORM_DEVICE__PLATFORM_DEVICE_H_ */ diff --git a/repos/dde_linux/src/drivers/usb_host/spec/arndale/platform.cc b/repos/dde_linux/src/drivers/usb_host/spec/arndale/platform.cc new file mode 100644 index 000000000..89acfff92 --- /dev/null +++ b/repos/dde_linux/src/drivers/usb_host/spec/arndale/platform.cc @@ -0,0 +1,340 @@ +/* + * \brief EHCI for Arndale initialization code + * \author Sebastian Sumpf + * \date 2013-02-20 + */ + +/* + * Copyright (C) 2013-2017 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +/* Genode */ +#include +#include +#include +#include +#include +#include +#include + +/* Emulation */ +#include +#include + + +using namespace Genode; + +enum { + EHCI_BASE = 0x12110000, + DWC3_BASE = 0x12000000, + DWC3_PHY_BASE = 0x12100000, + GPIO_BASE = 0x11400000, + EHCI_IRQ = Arndale::USB_HOST20_IRQ, + DWC3_IRQ = Arndale::USB_DRD30_IRQ, +}; + +static resource _ehci[] = +{ + { EHCI_BASE, EHCI_BASE + 0xfff, "ehci", IORESOURCE_MEM }, + { EHCI_IRQ, EHCI_IRQ, "ehci-irq", IORESOURCE_IRQ }, +}; + +static resource _dwc3[] = +{ + { DWC3_BASE, DWC3_BASE + 0xcfff, "dwc3", IORESOURCE_MEM }, + { DWC3_IRQ, DWC3_IRQ, "dwc3-irq", IORESOURCE_IRQ }, +}; + + +/** + * EHCI controller + */ +struct Ehci : Genode::Mmio +{ + Ehci(addr_t const mmio_base) : Mmio(mmio_base) + { + write(0); + + /* reset */ + write(1); + + while(read()) + msleep(1); + } + + struct Cmd : Register<0x10, 32> + { + struct Reset : Bitfield<1, 1> { }; + }; +}; + + +/** + * Gpio handling + */ +struct Gpio_bank { + unsigned con; + unsigned dat; +}; + + +static inline +unsigned con_mask(unsigned val) { return 0xf << ((val) << 2); } + + +static inline +unsigned con_sfr(unsigned x, unsigned v) { return (v) << ((x) << 2); } + + +static void gpio_cfg_pin(Gpio_bank *bank, int gpio, int cfg) +{ + unsigned int value; + + value = readl(&bank->con); + value &= ~con_mask(gpio); + value |= con_sfr(gpio, cfg); + writel(value, &bank->con); +} + + +static void gpio_direction_output(Gpio_bank *bank, int gpio, int en) +{ + unsigned int value; + enum { GPIO_OUTPUT = 0x1 }; + + gpio_cfg_pin(bank, gpio, GPIO_OUTPUT); + + value = readl(&bank->dat); + value &= ~(0x1 << gpio); + if (en) + value |= 0x1 << gpio; + writel(value, &bank->dat); +} + + +static void arndale_ehci_init(Genode::Env &env) +{ + enum Gpio_offset { D1 = 0x180, X3 = 0xc60 }; + + /* enable USB3 clock and power up */ + static Regulator::Connection reg_clk(env, Regulator::CLK_USB20); + reg_clk.state(true); + + static Regulator::Connection reg_pwr(env, Regulator::PWR_USB20); + reg_pwr.state(true); + + /* reset hub via GPIO */ + Io_mem_connection io_gpio(env, GPIO_BASE, 0x1000); + addr_t gpio_base = (addr_t)env.rm().attach(io_gpio.dataspace()); + + Gpio_bank *d1 = reinterpret_cast(gpio_base + D1); + Gpio_bank *x3 = reinterpret_cast(gpio_base + X3); + + /* hub reset */ + gpio_direction_output(x3, 5, 0); + /* hub connect */ + gpio_direction_output(d1, 7, 0); + + gpio_direction_output(x3, 5, 1); + gpio_direction_output(d1, 7, 1); + + env.rm().detach(gpio_base); + + /* reset ehci controller */ + Io_mem_connection io_ehci(env, EHCI_BASE, 0x1000); + addr_t ehci_base = (addr_t)env.rm().attach(io_ehci.dataspace()); + + Ehci ehci(ehci_base); + env.rm().detach(ehci_base); +} + + +struct Phy_usb3 : Genode::Mmio +{ + struct Link_system : Register<0x4, 32> + { + struct Fladj : Bitfield<1, 6> { }; + struct Ehci_version_control : Bitfield<27, 1> { }; + }; + + struct Phy_utmi : Register<0x8, 32> { }; + + struct Phy_clk_rst : Register<0x10, 32> + { + struct Common_onn : Bitfield<0, 1> { }; + struct Port_reset : Bitfield<1, 1> { }; + struct Ref_clk_sel : Bitfield<2, 2> { }; + struct Retenablen : Bitfield<4, 1> { }; + struct Fsel : Bitfield<5, 6> { }; + struct Mpll_mult : Bitfield<11, 7> { }; + struct Ref_ssp_en : Bitfield<19, 1> { }; + struct Ssc_en : Bitfield<20, 1> { }; + struct Ssc_ref_clk_sel : Bitfield<23, 8> { }; + }; + + struct Phy_reg0 : Register<0x14, 32> { }; + + struct Phy_param0 : Register<0x1c, 32> + { + struct Loss_level : Bitfield<26, 5> { }; + struct Ref_use_pad : Bitfield<31, 1> { }; + }; + + struct Phy_param1 : Register<0x20, 32> + { + struct Pcs_txdeemph : Bitfield<0, 5> { }; + }; + + struct Phy_test : Register<0x28, 32> + { + struct Power_down_ssb_hsb : Bitfield<2, 2> { }; + }; + + struct Phy_batchg : Register<0x30, 32> + { + struct Utmi_clksel : Bitfield<2, 1> { }; + }; + + struct Phy_resume : Register<0x34, 32> { }; + + Phy_usb3 (Genode::Env & env, addr_t const base) : Mmio(base) + { + Timer::Connection timer(env); + + /* reset */ + write(0); + + /* clock source */ + write(0); + + /* set Loss-of-Signal Detector sensitivity */ + write(0x9); + write(0); + + /* + * Setting the Frame length Adj value[6:1] to default 0x20 + * See xHCI 1.0 spec, 5.2.4 + */ + write(1); + write(0x20); + + /* set Tx De-Emphasis level */ + write(0x1c); + + /* set clock */ + write(1); + + /* PHYTEST POWERDOWN Control */ + write(0); + + /* UTMI power */ + enum { OTG_DISABLE = (1 << 6) }; + write(OTG_DISABLE); + + /* setup clock */ + Phy_clk_rst::access_t clk = 0; + + /* + * Use same reference clock for high speed + * as for super speed + */ + Phy_clk_rst::Ref_clk_sel::set(clk, 0x2); + /* 24 MHz */ + Phy_clk_rst::Fsel::set(clk, 0x2a); + Phy_clk_rst::Mpll_mult::set(clk, 0x68); + Phy_clk_rst::Ssc_ref_clk_sel::set(clk, 0x88); + + /* port reset */ + Phy_clk_rst::Port_reset::set(clk, 1); + + /* digital power supply in normal operating mode */ + Phy_clk_rst::Retenablen::set(clk, 1); + /* enable ref clock for SS function */ + Phy_clk_rst::Ref_ssp_en::set(clk, 1); + /* enable spread spectrum */ + Phy_clk_rst::Ssc_en::set(clk, 1); + /* power down HS Bias and PLL blocks in suspend mode */ + Phy_clk_rst::Common_onn::set(clk, 1); + + write(clk); + timer.usleep(10); + write(0); + } +}; + + +static void arndale_xhci_init(Genode::Env &env) +{ + /* enable USB3 clock and power up */ + static Regulator::Connection reg_clk(env, Regulator::CLK_USB30); + reg_clk.state(true); + + static Regulator::Connection reg_pwr(env, Regulator::PWR_USB30); + reg_pwr.state(true); + + /* setup PHY */ + Attached_io_mem_dataspace io_phy(env, DWC3_PHY_BASE, 0x1000); + Phy_usb3 phy(env, (addr_t)io_phy.local_addr()); +} + + +extern "C" void module_ehci_exynos_init(); +extern "C" void module_dwc3_driver_init(); +extern "C" void module_xhci_plat_init(); + + +void ehci_setup(Services *services) +{ + /* register EHCI controller */ + module_ehci_exynos_init(); + + /* setup controller */ + arndale_ehci_init(services->env); + + /* setup EHCI-controller platform device */ + platform_device *pdev = (platform_device *)kzalloc(sizeof(platform_device), 0); + pdev->name = (char *)"exynos-ehci"; + pdev->id = 0; + pdev->num_resources = 2; + pdev->resource = _ehci; + + /*needed for DMA buffer allocation. See 'hcd_buffer_alloc' in 'buffer.c' */ + static u64 dma_mask = ~(u64)0; + pdev->dev.dma_mask = &dma_mask; + pdev->dev.coherent_dma_mask = ~0; + + platform_device_register(pdev); +} + + +void xhci_setup(Services *services) +{ + module_dwc3_driver_init(); + module_xhci_plat_init(); + + arndale_xhci_init(services->env); + + /* setup DWC3-controller platform device */ + platform_device *pdev = (platform_device *)kzalloc(sizeof(platform_device), 0); + pdev->name = (char *)"dwc3"; + pdev->id = 0; + pdev->num_resources = 2; + pdev->resource = _dwc3; + + /*needed for DMA buffer allocation. See 'hcd_buffer_alloc' in 'buffer.c' */ + static u64 dma_mask = ~(u64)0; + pdev->dev.dma_mask = &dma_mask; + pdev->dev.coherent_dma_mask = ~0; + + platform_device_register(pdev); +} + + +void platform_hcd_init(Services *services) +{ + ehci_setup(services); + xhci_setup(services); +} diff --git a/repos/dde_linux/src/drivers/usb_host/spec/arndale/target.mk b/repos/dde_linux/src/drivers/usb_host/spec/arndale/target.mk new file mode 100644 index 000000000..f33b2842d --- /dev/null +++ b/repos/dde_linux/src/drivers/usb_host/spec/arndale/target.mk @@ -0,0 +1,22 @@ +include $(REP_DIR)/src/drivers/usb_host/target.inc + +TARGET = arndale_usb_host_drv +REQUIRES = arndale + +INC_DIR += $(REP_DIR)/src/drivers/usb_host/spec/arm +INC_DIR += $(REP_DIR)/src/include/spec/arm + +SRC_CC += spec/arm/platform.cc +SRC_CC += spec/arndale/platform.cc + +SRC_C += usb/dwc3/core.c +SRC_C += usb/dwc3/dwc3-exynos.c +SRC_C += usb/dwc3/host.c +SRC_C += usb/host/ehci-exynos.c +SRC_C += usb/host/xhci-plat.c + +CC_OPT += -DCONFIG_USB_EHCI_TT_NEWSCHED=1 +CC_OPT += -DCONFIG_USB_DWC3_HOST=1 +CC_OPT += -DCONFIG_USB_OTG_UTILS=1 +CC_OPT += -DCONFIG_USB_XHCI_PLATFORM=1 +CC_OPT += -DDWC3_QUIRK diff --git a/repos/dde_linux/src/drivers/usb_host/spec/odroid_x2/platform.cc b/repos/dde_linux/src/drivers/usb_host/spec/odroid_x2/platform.cc new file mode 100644 index 000000000..21e1b6fde --- /dev/null +++ b/repos/dde_linux/src/drivers/usb_host/spec/odroid_x2/platform.cc @@ -0,0 +1,207 @@ +/* + * \brief EHCI for Odroid-x2 initializaion code + * \author Sebastian Sumpf + * \author Alexy Gallardo Segura + * \author Humberto Lopez Leon + * \author Reinir Millo Sanchez + * \date 2015-07-08 + */ + +/* + * Copyright (C) 2015-2017 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +/* Genode */ +#include +#include +#include +#include +#include +#include +#include +#include + +/* Emulation */ +#include +#include + +using namespace Genode; + + +enum Usb_masks { + PHY0_NORMAL_MASK = 0x39 << 0, + PHY0_SWRST_MASK = 0x7 << 0, + PHY1_STD_NORMAL_MASK = 0x7 << 6, + EXYNOS4X12_HSIC0_NORMAL_MASK = 0x7 << 9, + EXYNOS4X12_HSIC1_NORMAL_MASK = 0x7 << 12, + EXYNOS4X12_HOST_LINK_PORT_SWRST_MASK = 0xf << 7, + EXYNOS4X12_PHY1_SWRST_MASK = 0xf << 3, +}; + +enum { + /*The EHCI base is taken from linux kernel */ + EHCI_BASE = 0x12580000, + GPIO_BASE = 0x11000000, + USBOTG = 0x125B0000, + EHCI_IRQ = Odroid_x2::USB_HOST20_IRQ, +}; + +static resource _ehci[] = +{ + { EHCI_BASE, EHCI_BASE + 0xfff, "ehci", IORESOURCE_MEM }, + { EHCI_IRQ, EHCI_IRQ, "ehci-irq", IORESOURCE_IRQ }, +}; + + +/** + * EHCI controller + */ +struct Ehci : Genode::Mmio +{ + Ehci(addr_t const mmio_base) : Mmio(mmio_base) + { + write(0); + + /* reset */ + write(1); + + while(read()) + msleep(1); + } + + struct Cmd : Register<0x10, 32> + { + struct Reset : Bitfield<1, 1> { }; + }; +}; + +/** + * USB OTG handling + */ +struct Usb_otg : Genode::Mmio +{ + Usb_otg(Genode::Env &env, Genode::addr_t base) + : Genode::Mmio (base) + { + Timer::Connection timer(env); + unsigned int rstcon_mask = 0; + unsigned int phyclk_mask = 5; + unsigned int phypwr_mask = 0; + + /*set the clock of device*/ + write(phyclk_mask); + rstcon_mask= read(); + + /* set to normal of Device */ + phypwr_mask= read() & ~PHY0_NORMAL_MASK; + write(phypwr_mask); + + /* set to normal of Host */ + phypwr_mask=read(); + phypwr_mask &= ~(PHY1_STD_NORMAL_MASK + |EXYNOS4X12_HSIC0_NORMAL_MASK + |EXYNOS4X12_HSIC1_NORMAL_MASK); + write(phypwr_mask); + + /* reset both PHY and Link of Device */ + rstcon_mask = read() | PHY0_SWRST_MASK; + write(rstcon_mask); + timer.usleep(10); + rstcon_mask &= ~PHY0_SWRST_MASK; + write(rstcon_mask); + + /* reset both PHY and Link of Host */ + rstcon_mask = read() + |EXYNOS4X12_HOST_LINK_PORT_SWRST_MASK + |EXYNOS4X12_PHY1_SWRST_MASK; + write(rstcon_mask); + timer.usleep(10); + rstcon_mask &= ~(EXYNOS4X12_HOST_LINK_PORT_SWRST_MASK + |EXYNOS4X12_PHY1_SWRST_MASK); + write(rstcon_mask); + timer.usleep(10); + } + struct Phypwr : Register <0x0,32>{}; + struct Phyclk : Register <0x4,32>{}; + struct Rstcon : Register <0x8,32>{}; +}; + +static void clock_pwr_init(Genode::Env &env) +{ + /* enable USB2 clock and power up */ + static Regulator::Connection reg_clk(env, Regulator::CLK_USB20); + reg_clk.state(true); + + static Regulator::Connection reg_pwr(env, Regulator::PWR_USB20); + reg_pwr.state(true); +} + +static void usb_phy_init(Genode::Env &env) +{ + Io_mem_connection io_usbotg(env, USBOTG, 0x1000); + addr_t usbotg_base = (addr_t)env.rm().attach(io_usbotg.dataspace()); + Usb_otg usbotg(env, usbotg_base); + env.rm().detach(usbotg_base); +} + +static void odroidx2_ehci_init(Genode::Env &env) +{ + clock_pwr_init(env); + usb_phy_init(env); + + /* reset hub via GPIO */ + enum { X30 = 294, X34 = 298, X35 = 299 }; + + Gpio::Connection gpio_x30(env, X30); + Gpio::Connection gpio_x34(env, X34); + Gpio::Connection gpio_x35(env, X35); + + /* Set Ref freq 0 => 24MHz, 1 => 26MHz*/ + /* Odroid Us have it at 24MHz, Odroid Xs at 26MHz */ + gpio_x30.write(true); + + /* Disconnect, Reset, Connect */ + gpio_x34.write(false); + gpio_x35.write(false); + gpio_x35.write(true); + gpio_x34.write(true); + + /* reset ehci controller */ + Io_mem_connection io_ehci(env, EHCI_BASE, 0x1000); + addr_t ehci_base = (addr_t)env.rm().attach(io_ehci.dataspace()); + + Ehci ehci(ehci_base); + + env.rm().detach(ehci_base); +} + +extern "C" void module_ehci_exynos_init(); +extern "C" int module_usbnet_init(); +extern "C" int module_smsc95xx_driver_init(); + + +void platform_hcd_init(Services *services) +{ + /* register EHCI controller */ + module_ehci_exynos_init(); + + /* setup controller */ + odroidx2_ehci_init(services->env); + + /* setup EHCI-controller platform device */ + platform_device *pdev = (platform_device *)kzalloc(sizeof(platform_device), 0); + pdev->name = (char *)"exynos-ehci"; + pdev->id = 0; + pdev->num_resources = 2; + pdev->resource = _ehci; + + /*needed for DMA buffer allocation. See 'hcd_buffer_alloc' in 'buffer.c' */ + static u64 dma_mask = ~(u64)0; + pdev->dev.dma_mask = &dma_mask; + pdev->dev.coherent_dma_mask = ~0; + + platform_device_register(pdev); +} diff --git a/repos/dde_linux/src/drivers/usb_host/spec/odroid_x2/target.mk b/repos/dde_linux/src/drivers/usb_host/spec/odroid_x2/target.mk new file mode 100644 index 000000000..16a063904 --- /dev/null +++ b/repos/dde_linux/src/drivers/usb_host/spec/odroid_x2/target.mk @@ -0,0 +1,14 @@ +include $(REP_DIR)/src/drivers/usb_host/target.inc + +TARGET = odroid_x2_usb_host_drv +REQUIRES = odroid_x2 + +INC_DIR += $(REP_DIR)/src/drivers/usb_host/spec/arm +INC_DIR += $(REP_DIR)/src/include/spec/arm + +SRC_CC += spec/arm/platform.cc +SRC_CC += spec/odroid_x2/platform.cc + +SRC_C += usb/host/ehci-exynos.c + +CC_OPT += -DCONFIG_USB_OTG_UTILS=1 diff --git a/repos/dde_linux/src/drivers/usb_host/spec/panda/platform.cc b/repos/dde_linux/src/drivers/usb_host/spec/panda/platform.cc new file mode 100644 index 000000000..291c9203d --- /dev/null +++ b/repos/dde_linux/src/drivers/usb_host/spec/panda/platform.cc @@ -0,0 +1,309 @@ +/* + * \brief EHCI for OMAP4 + * \author Sebastian Sumpf + * \date 2012-06-20 + */ + +/* + * Copyright (C) 2012-2017 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +#include + +#include +#include +#include +#include + +#include + +#include + +using namespace Genode; + +/** + * Base addresses + */ +enum { + EHCI_BASE = 0x4a064c00, + UHH_BASE = 0x4a064000, + TLL_BASE = 0x4a062000, + SCRM_BASE = 0x4a30a000, + CAM_BASE = 0x4a009000, /* used for L3INIT_CM2 */ +}; + + +/** + * Inerrupt numbers + */ +enum { IRQ_EHCI = Panda::HSUSB_EHCI_IRQ }; + + +/** + * Resources for platform device + */ +static resource _ehci[] = +{ + { EHCI_BASE, EHCI_BASE + 0x400 - 1, "ehci", IORESOURCE_MEM }, + { IRQ_EHCI, IRQ_EHCI, "ehci-irq", IORESOURCE_IRQ }, +}; + + +/** + * Port informations for platform device + */ +static struct ehci_hcd_omap_platform_data _ehci_data; + + +/** + * Enables USB clocks + */ +struct Clocks : Genode::Mmio +{ + Clocks(Genode::addr_t const mmio_base) : Mmio(mmio_base) + { + write(0x101); + write(0x1008002); + write(0x1); + } + + struct Usb_host_clk : Register<0x358, 32> { }; + struct Usb_tll_clk : Register<0x368, 32> { }; + struct Usb_phy_clk : Register<0x3e0, 32> { }; + + template void update(unsigned val) + { + typename T::access_t access = read(); + access |= val; + write(access); + }; + + void dump() + { + Usb_host_clk::access_t a1 = read(); + Usb_tll_clk::access_t a3 = read(); + Usb_phy_clk::access_t a4 = read(); + } +}; + + +/** + * Panda board reference USB clock + */ +struct Aux3 : Genode::Mmio +{ + Aux3(addr_t const mmio_base) : Mmio(mmio_base) + { + enable(); + } + + /* the clock register */ + struct Aux3_clk : Register<0x31c, 32> + { + struct Src_select : Bitfield<1, 2> { }; + struct Div : Bitfield<16, 4> { enum { DIV_2 = 1 }; }; + struct Enable : Bitfield<8, 1> { enum { ON = 1 }; }; + }; + + /* clock source register */ + struct Aux_src : Register<0x110, 32, true> { }; + + void enable() + { + /* select system clock */ + write(0); + + /* set to 19.2 Mhz */ + write(Aux3_clk::Div::DIV_2); + + /* enable clock */ + write(Aux3_clk::Enable::ON); + + /* enable_ext = 1 | enable_int = 1| mode = 0x01 */ + write(0xd); + } +}; + + +/** + * ULPI transceiverless link + */ +struct Tll : Genode::Mmio +{ + Tll(addr_t const mmio_base) : Mmio(mmio_base) + { + reset(); + } + + struct Sys_config : Register<0x10, 32> + { + struct Soft_reset : Bitfield<1, 1> { }; + struct Cactivity : Bitfield<8, 1> { }; + struct Sidle_mode : Bitfield<3, 2> { }; + struct Ena_wakeup : Bitfield<2, 1> { }; + }; + + struct Sys_status : Register<0x14, 32> { }; + + void reset() + { + write(0x0); + + /* reset */ + write(0x1); + + while(!read()) + msleep(1); + + /* disable IDLE, enable wake up, enable auto gating */ + write(1); + write(1); + write(1); + } +}; + + +/** + * USB high-speed host + */ +struct Uhh : Genode::Mmio +{ + Uhh(addr_t const mmio_base) : Mmio(mmio_base) + { + /* diable idle and standby */ + write(1); + write(1); + + /* set ports to external phy */ + write(0); + write(0); + } + + struct Sys_config : Register<0x10, 32> + { + struct Idle : Bitfield<2, 2> { }; + struct Standby : Bitfield<4, 2> { }; + }; + + struct Host_config : Register<0x40, 32> + { + struct P1_mode : Bitfield<16, 2> { }; + struct P2_mode : Bitfield<18, 2> { }; + }; +}; + + +/** + * EHCI controller + */ +struct Ehci : Genode::Mmio +{ + Ehci(addr_t const mmio_base) : Mmio(mmio_base) + { + write(0); + + /* reset */ + write(1); + + while(read()) + msleep(1); + } + + struct Cmd : Register<0x10, 32> + { + struct Reset : Bitfield<1, 1> { }; + }; +}; + + +/** + * Initialize the USB controller from scratch, since the boot loader might not + * do it or even disable USB. + */ +static void omap_ehci_init(Genode::Env &env) +{ + /* taken from the Panda board manual */ + enum { HUB_POWER = 1, HUB_NRESET = 62, ULPI_PHY_TYPE = 182 }; + + /* SCRM */ + Io_mem_connection io_scrm(env, SCRM_BASE, 0x1000); + addr_t scrm_base = (addr_t)env.rm().attach(io_scrm.dataspace()); + + /* enable reference clock */ + Aux3 aux3(scrm_base); + + /* init GPIO */ + Gpio::Connection gpio_power(env, HUB_POWER); + Gpio::Connection gpio_reset(env, HUB_NRESET); + + /* disable the hub power and reset before init */ + gpio_power.direction(Gpio::Session::OUT); + gpio_reset.direction(Gpio::Session::OUT); + gpio_power.write(false); + gpio_reset.write(true); + + /* enable clocks */ + Io_mem_connection io_clock(env, CAM_BASE, 0x1000); + addr_t clock_base = (addr_t)env.rm().attach(io_clock.dataspace()); + Clocks c(clock_base); + + /* reset TLL */ + Io_mem_connection io_tll(env, TLL_BASE, 0x1000); + addr_t tll_base = (addr_t)env.rm().attach(io_tll.dataspace()); + Tll t(tll_base); + + /* reset host */ + Io_mem_connection io_uhh(env, UHH_BASE, 0x1000); + addr_t uhh_base = (addr_t)env.rm().attach(io_uhh.dataspace()); + Uhh uhh(uhh_base); + + /* enable hub power */ + gpio_power.write(true); + + /* reset EHCI */ + addr_t ehci_base = uhh_base + 0xc00; + Ehci ehci(ehci_base); + + addr_t base[] = { scrm_base, clock_base, tll_base, uhh_base, 0 }; + for (int i = 0; base[i]; i++) + env.rm().detach(base[i]); +} + + +extern "C" void module_ehci_omap_init(); +extern "C" int module_usbnet_init(); +extern "C" int module_smsc95xx_driver_init(); + +void platform_hcd_init(Services *services) +{ + /* register EHCI controller */ + module_ehci_omap_init(); + + /* initialize EHCI */ + omap_ehci_init(services->env); + + /* setup EHCI-controller platform device */ + platform_device *pdev = (platform_device *)kzalloc(sizeof(platform_device), 0); + pdev->name = (char *)"ehci-omap"; + pdev->id = 0; + pdev->num_resources = 2; + pdev->resource = _ehci; + + + _ehci_data.port_mode[0] = OMAP_EHCI_PORT_MODE_PHY; + _ehci_data.port_mode[1] = OMAP_USBHS_PORT_MODE_UNUSED; + _ehci_data.phy_reset = 0; + pdev->dev.platform_data = &_ehci_data; + + /* + * Needed for DMA buffer allocation. See 'hcd_buffer_alloc' in 'buffer.c' + */ + static u64 dma_mask = ~(u64)0; + pdev->dev.dma_mask = &dma_mask; + pdev->dev.coherent_dma_mask = ~0; + + platform_device_register(pdev); +} diff --git a/repos/dde_linux/src/drivers/usb_host/spec/panda/target.mk b/repos/dde_linux/src/drivers/usb_host/spec/panda/target.mk new file mode 100644 index 000000000..f176f3f2f --- /dev/null +++ b/repos/dde_linux/src/drivers/usb_host/spec/panda/target.mk @@ -0,0 +1,15 @@ +include $(REP_DIR)/src/drivers/usb_host/target.inc + +TARGET = panda_usb_host_drv +REQUIRES = panda + +INC_DIR += $(REP_DIR)/src/drivers/usb_host/spec/arm +INC_DIR += $(REP_DIR)/src/include/spec/arm + +SRC_CC += spec/arm/platform.cc +SRC_CC += spec/panda/platform.cc +SRC_C += usb/host/ehci-omap.c + +CC_OPT += -DCONFIG_USB_EHCI_HCD_OMAP=1 +CC_OPT += -DCONFIG_USB_EHCI_TT_NEWSCHED=1 +CC_OPT += -DCONFIG_EXTCON=1 diff --git a/repos/dde_linux/src/drivers/usb_host/spec/rpi/platform.cc b/repos/dde_linux/src/drivers/usb_host/spec/rpi/platform.cc new file mode 100644 index 000000000..781b88531 --- /dev/null +++ b/repos/dde_linux/src/drivers/usb_host/spec/rpi/platform.cc @@ -0,0 +1,84 @@ +/* + * \brief USB initialization for Raspberry Pi + * \author Norman Feske + * \date 2013-09-11 + */ + +/* + * Copyright (C) 2013-2017 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +/* Genode includes */ +#include +#include +#include + + +/* emulation */ +#include +#include +#include + +/* dwc-otg */ +#define new new_ +#include +#undef new + +using namespace Genode; + +unsigned dwc_irq(); + + +/************************************************ + ** Resource info passed to the dwc_otg driver ** + ************************************************/ + +enum { + DWC_BASE = 0x20980000, + DWC_SIZE = 0x20000, +}; + + +static resource _dwc_otg_resource[] = +{ + { DWC_BASE, DWC_BASE + DWC_SIZE - 1, "dwc_otg", IORESOURCE_MEM }, + { dwc_irq(), dwc_irq(), "dwc_otg-irq" /* name unused */, IORESOURCE_IRQ } +}; + + +/******************* + ** Init function ** + *******************/ + +extern "C" void module_dwc_otg_driver_init(); +extern bool fiq_enable, fiq_fsm_enable; + +void platform_hcd_init(Services *services) +{ + /* enable USB power */ + Platform::Connection platform(services->env); + platform.power_state(Platform::Session::POWER_USB_HCD, true); + + /* disable fiq optimization */ + fiq_enable = false; + fiq_fsm_enable = false; + + module_dwc_otg_driver_init(); + + /* setup host-controller platform device */ + platform_device *pdev = (platform_device *)kzalloc(sizeof(platform_device), 0); + pdev->name = (char *)"dwc_otg"; + pdev->id = 0; + pdev->num_resources = sizeof(_dwc_otg_resource)/sizeof(resource); + pdev->resource = _dwc_otg_resource; + + /* needed for DMA buffer allocation. See 'hcd_buffer_alloc' in 'buffer.c' */ + static u64 dma_mask = ~(u64)0; + pdev->dev.dma_mask = &dma_mask; + pdev->dev.coherent_dma_mask = ~0; + + platform_device_register(pdev); +} diff --git a/repos/dde_linux/src/drivers/usb_host/spec/rpi/target.mk b/repos/dde_linux/src/drivers/usb_host/spec/rpi/target.mk new file mode 100644 index 000000000..5f9bd96f9 --- /dev/null +++ b/repos/dde_linux/src/drivers/usb_host/spec/rpi/target.mk @@ -0,0 +1,49 @@ +include $(REP_DIR)/src/drivers/usb_host/target.inc + +TARGET = rpi_usb_host_drv +REQUIRES = rpi + +INC_DIR += $(REP_DIR)/src/drivers/usb_host/spec/arm +INC_DIR += $(REP_DIR)/src/include/spec/arm + +SRC_CC += spec/arm/platform.cc +SRC_CC += spec/rpi/platform.cc + +SRC_C += dwc_common_port/dwc_cc.c +SRC_C += dwc_common_port/dwc_common_linux.c +SRC_C += dwc_common_port/dwc_crypto.c +SRC_C += dwc_common_port/dwc_dh.c +SRC_C += dwc_common_port/dwc_mem.c +SRC_C += dwc_common_port/dwc_modpow.c +SRC_C += dwc_common_port/dwc_notifier.c +SRC_C += dwc_otg/dwc_otg_adp.c +SRC_C += dwc_otg/dwc_otg_attr.c +SRC_C += dwc_otg/dwc_otg_cfi.c +SRC_C += dwc_otg/dwc_otg_cil.c +SRC_C += dwc_otg/dwc_otg_cil_intr.c +SRC_C += dwc_otg/dwc_otg_driver.c +SRC_C += dwc_otg/dwc_otg_hcd.c +SRC_C += dwc_otg/dwc_otg_hcd_ddma.c +SRC_C += dwc_otg/dwc_otg_hcd_intr.c +SRC_C += dwc_otg/dwc_otg_hcd_linux.c +SRC_C += dwc_otg/dwc_otg_hcd_queue.c + +CC_OPT += -DDWC_LINUX -DPLATFORM_INTERFACE + +# needed for 'ehci-hcd.c', which we don't use on the rpi, but it is still +# part of the generic usb USB driver +CC_OPT += -DCONFIG_USB_EHCI_PCI=1 + +# for 'dwc_otg_hcd_linux.c' for enabling the FIQ, which we don't use anyway +CC_OPT += -DINTERRUPT_VC_USB=9 + +# for 'dwc_otg_driver.c' for preventing calls to set_irq_type +CC_OPT += -DIRQF_TRIGGER_LOW=1 + +INC_DIR += $(LX_CONTRIB_DIR)/drivers/usb/host/dwc_common_port \ + $(LX_CONTRIB_DIR)/drivers/usb/host/dwc_otg \ + $(REP_DIR)/src/lib/usb_host/spec/arm + +vpath %.c $(LX_CONTRIB_DIR)/drivers/usb/host + +LIBS += rpi_usb diff --git a/repos/dde_linux/src/drivers/usb_host/spec/wand_quad/platform.cc b/repos/dde_linux/src/drivers/usb_host/spec/wand_quad/platform.cc new file mode 100644 index 000000000..7c5a79565 --- /dev/null +++ b/repos/dde_linux/src/drivers/usb_host/spec/wand_quad/platform.cc @@ -0,0 +1,132 @@ +/* + * \brief EHCI for Freescale i.MX6 + * \author Stefan Kalkowski + * \date 2018-04-11 + */ + +/* + * Copyright (C) 2018 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +#include +#include + +extern "C" int module_ci_hdrc_platform_register(); +extern "C" int module_ci_hdrc_imx_driver_init(); +extern "C" int module_usbmisc_imx_driver_init(); +extern "C" int postcore_mxs_phy_module_init(); + +extern "C" void module_ehci_hcd_init(); +extern "C" void module_xhci_hcd_init(); + +void platform_hcd_init(Services *services) +{ + module_ehci_hcd_init(); + module_ci_hdrc_platform_register(); + postcore_mxs_phy_module_init(); + module_usbmisc_imx_driver_init(); + module_ci_hdrc_imx_driver_init(); + + /* USB PHY initialization */ + { + static resource usbphy_res[] = + { + { 0x020ca000, 0x020cafff, "usbphy", IORESOURCE_MEM }, + { 77, 77, "usbphy-irq", IORESOURCE_IRQ }, + }; + + platform_device *pdev = (platform_device *)kzalloc(sizeof(platform_device), 0); + pdev->name = (char *)"mxs_phy"; + pdev->id = 0; + pdev->num_resources = 2; + pdev->resource = usbphy_res; + + pdev->dev.of_node = (device_node*)kzalloc(sizeof(device_node), 0); + pdev->dev.of_node->properties = (property*)kzalloc(sizeof(property), 0); + pdev->dev.of_node->properties->name = "compatible"; + pdev->dev.of_node->properties->value = (void*)"fsl,imx6q-usbphy"; + pdev->dev.of_node->properties->next = (property*)kzalloc(sizeof(property), 0); + pdev->dev.of_node->properties->next->name = "fsl,anatop"; + pdev->dev.of_node->properties->next->value = (void*)0xdeaddead; + + platform_device_register(pdev); + } + + device_node * usbmisc_of_node = nullptr; + + /* USB MISC initialization */ + { + static resource usbmisc_res[] = { { 0x02184800, 0x021849ff, "usbmisc", IORESOURCE_MEM }, }; + + platform_device *pdev = (platform_device *)kzalloc(sizeof(platform_device), 0); + pdev->name = (char *)"usbmisc_imx"; + pdev->id = 1; + pdev->num_resources = 1; + pdev->resource = usbmisc_res; + + pdev->dev.of_node = (device_node*)kzalloc(sizeof(device_node), 0); + pdev->dev.of_node->properties = (property*)kzalloc(sizeof(property), 0); + pdev->dev.of_node->properties->name = "compatible"; + pdev->dev.of_node->properties->value = (void*)"fsl,imx6q-usbmisc"; + pdev->dev.of_node->dev = &pdev->dev; + usbmisc_of_node = pdev->dev.of_node; + + platform_device_register(pdev); + } + + /* setup EHCI-controller platform device */ + { + static resource ehci_res[] = + { + { 0x02184200, 0x021843ff, "imx_usb", IORESOURCE_MEM }, + { 72, 72, "imx_usb-irq", IORESOURCE_IRQ }, + }; + + platform_device *pdev = (platform_device *)kzalloc(sizeof(platform_device), 0); + pdev->name = (char *)"imx_usb"; + pdev->id = 2; + pdev->num_resources = 2; + pdev->resource = ehci_res; + + pdev->dev.of_node = (device_node*)kzalloc(sizeof(device_node), 0); + pdev->dev.of_node->properties = (property*)kzalloc(sizeof(property), 0); + pdev->dev.of_node->properties->name = "compatible"; + pdev->dev.of_node->properties->value = (void*)"fsl,imx6q-usb"; + pdev->dev.of_node->properties->next = (property*)kzalloc(sizeof(property), 0); + pdev->dev.of_node->properties->next->name = "fsl,usbmisc"; + pdev->dev.of_node->properties->next->value = (void*)usbmisc_of_node; + pdev->dev.of_node->properties->next->next = (property*)kzalloc(sizeof(property), 0); + pdev->dev.of_node->properties->next->next->name = "dr_mode"; + pdev->dev.of_node->properties->next->next->value = (void*)"host"; + + /* + * Needed for DMA buffer allocation. See 'hcd_buffer_alloc' in 'buffer.c' + */ + static u64 dma_mask = ~(u64)0; + pdev->dev.dma_mask = &dma_mask; + pdev->dev.coherent_dma_mask = ~0; + + platform_device_register(pdev); + } +} + +extern "C" int devm_extcon_register_notifier(struct device *dev, struct extcon_dev *edev, unsigned int id, struct notifier_block *nb) +{ + BUG(); + return -1; +} + +extern "C" struct extcon_dev *extcon_get_edev_by_phandle(struct device *dev, int index) +{ + BUG(); + return NULL; +} + +extern "C" int extcon_get_state(struct extcon_dev *edev, unsigned int id) +{ + BUG(); + return -1; +} diff --git a/repos/dde_linux/src/drivers/usb_host/spec/wand_quad/target.mk b/repos/dde_linux/src/drivers/usb_host/spec/wand_quad/target.mk new file mode 100644 index 000000000..0583fa3c9 --- /dev/null +++ b/repos/dde_linux/src/drivers/usb_host/spec/wand_quad/target.mk @@ -0,0 +1,27 @@ +include $(REP_DIR)/src/drivers/usb_host/target.inc + +TARGET = wand_quad_usb_host_drv +REQUIRES = wand_quad + +SRC_C += usb/chipidea/ci_hdrc_imx.c +SRC_C += usb/chipidea/core.c +SRC_C += usb/chipidea/host.c +SRC_C += usb/chipidea/otg.c +SRC_C += usb/chipidea/usbmisc_imx.c +SRC_C += usb/phy/phy-mxs-usb.c + +INC_DIR += $(REP_DIR)/src/drivers/usb_host/spec/arm +INC_DIR += $(REP_DIR)/src/include/spec/arm + +SRC_CC += spec/arm/platform.cc +SRC_CC += spec/wand_quad/platform.cc + +CC_OPT += -DCONFIG_USB_CHIPIDEA +CC_OPT += -DCONFIG_USB_CHIPIDEA_HOST +CC_OPT += -DCONFIG_USB_EHCI_HCD +CC_OPT += -DCONFIG_USB_EHCI_ROOT_HUB_TT +CC_OPT += -DCONFIG_USB_MXS_PHY +CC_OPT += -DCONFIG_USB_EHCI_TT_NEWSCHED=1 +CC_OPT += -DCONFIG_EXTCON=1 + +CC_C_OPT += -Wno-incompatible-pointer-types diff --git a/repos/dde_linux/src/drivers/usb_host/spec/x86/platform.cc b/repos/dde_linux/src/drivers/usb_host/spec/x86/platform.cc new file mode 100644 index 000000000..60117c7dd --- /dev/null +++ b/repos/dde_linux/src/drivers/usb_host/spec/x86/platform.cc @@ -0,0 +1,223 @@ +/* + * \brief PCI device handling + * \author Sebastian Sumpf + * \date 2016-04-25 + */ + +/* + * Copyright (C) 2016-2017 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +/* Genode includes */ +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + + +/** + * Quirks + */ +extern "C" void __pci_fixup_quirk_usb_early_handoff(void *data); + + +/** + * List of pci devices from platform driver + */ +class Pci_dev_list +{ + private: + + struct Element : public Lx_kit::List::Element + { + Platform::Device_capability cap; + + Element(Platform::Device_capability cap) : cap(cap) { } + }; + + Lx_kit::List _pci_caps; + + public: + + Pci_dev_list() + { + /* + * Obtain first device, the operation may exceed the session quota. + * So we use the 'with_upgrade' mechanism. + */ + Platform::Device_capability cap = + Lx::pci()->with_upgrade([&] () { + return Lx::pci()->first_device(); }); + + /* + * Iterate over the devices of the platform session. + */ + while (cap.valid()) { + + _pci_caps.insert(new (Lx::Malloc::mem()) Element(cap)); + + /* try next one. Upgrade session quota on demand.*/ + Lx::pci()->with_upgrade([&] () { + cap = Lx::pci()->next_device(cap); }); + } + } + + template + void for_each_pci_device(FUNC const &func) + { + for (Element *e = _pci_caps.first(); e; e = e->next()) + func(e->cap); + } +}; + + +Pci_dev_list *pci_dev_list() +{ + static Pci_dev_list _list; + return &_list; +} + + +extern "C" int pci_register_driver(struct pci_driver *driver) +{ + driver->driver.name = driver->name; + + pci_device_id const *id_table = driver->id_table; + if (!id_table) + return -ENODEV; + + using namespace Genode; + + bool found = false; + + auto lamda = [&] (Platform::Device_capability cap) { + + Platform::Device_client client(cap); + + /* request device ID from platform driver */ + unsigned const class_code = client.class_code(); + + /* look if we find the device ID in the driver's 'id_table' */ + pci_device_id const *matching_id = nullptr; + for (pci_device_id const *id = id_table; id->device; id++) { + + lx_log(DEBUG_PCI,"idclass: %x idclassm: %x devclass %x", id->class_, + id->class_mask, class_code); + + /* check for drivers that support any device for a given class */ + if (id->device != (unsigned)PCI_ANY_ID || !id->class_mask) + continue; + + if ((id->class_ & id->class_mask) == (class_code & id->class_mask)) { + matching_id = id; + break; + } + } + + /* skip device that is not handled by driver */ + if (!matching_id) + return false; + + /* create 'pci_dev' struct for matching device */ + Lx::Pci_dev *pci_dev = new (Lx::Malloc::mem()) Lx::Pci_dev(cap); + + /* enable ioremap to work */ + Lx::pci_dev_registry()->insert(pci_dev); + + /* register driver at the 'pci_dev' struct */ + pci_dev->dev.driver = &driver->driver; + + /* + * This quirk handles device handoff from BIOS, since the BIOS may still + * access the USB controller after bootup. For this the ext cap register of + * the PCI config space is checked + */ + if (Lx_kit::env().config_rom().xml().attribute_value("bios_handoff", true)) + __pci_fixup_quirk_usb_early_handoff(pci_dev); + + /* call probe function of the Linux driver */ + if (driver->probe(pci_dev, matching_id)) { + + /* if the probing failed, revert the creation of 'pci_dev' */ + pci_dev_put(pci_dev); + return false; + } + + found = true; + + /* multiple device support continue */ + return true; + }; + + pci_dev_list()->for_each_pci_device(lamda); + + return found ? 0 : -ENODEV; +} + + +/*********************** + ** linux/interrupt.h ** + ***********************/ + +int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, + const char *name, void *dev) +{ + for (Lx::Pci_dev *pci_dev = Lx::pci_dev_registry()->first(); pci_dev; pci_dev = pci_dev->next()) + if (pci_dev->irq == irq) { + Lx::Irq::irq().request_irq(pci_dev->client(), handler, dev); + return 0; + } + + return -ENODEV; +} + + +/********************************* + ** Platform backend alloc init ** + *********************************/ + +void backend_alloc_init(Genode::Env &env, Genode::Ram_session &ram, + Genode::Allocator &alloc) +{ + Lx::pci_init(env, ram, alloc); +} + + +extern "C" void module_ehci_hcd_init(); +extern "C" void module_ehci_pci_init(); +extern "C" void module_ohci_hcd_mod_init(); +extern "C" void module_ohci_pci_init(); +extern "C" void module_uhci_hcd_init(); +extern "C" void module_xhci_hcd_init(); +extern "C" void module_xhci_pci_init(); + +void platform_hcd_init(Services *s) +{ + module_xhci_hcd_init(); + module_xhci_pci_init(); + + /* ehci_hcd should always be loaded before uhci_hcd and ohci_hcd, not after */ + module_ehci_hcd_init(); + module_ehci_pci_init(); + + module_ohci_hcd_mod_init(); + module_ohci_pci_init(); + + module_uhci_hcd_init(); +} diff --git a/repos/dde_linux/src/drivers/usb_host/spec/x86/target.inc b/repos/dde_linux/src/drivers/usb_host/spec/x86/target.inc new file mode 100644 index 000000000..cfb6962aa --- /dev/null +++ b/repos/dde_linux/src/drivers/usb_host/spec/x86/target.inc @@ -0,0 +1,24 @@ +include $(REP_DIR)/src/drivers/usb_host/target.inc + +TARGET = x86_pc_usb_host_drv + +INC_DIR += $(REP_DIR)/src_drivers/usb_host/spec/x86 +INC_DIR += $(REP_DIR)/src/include/spec/x86 + +SRC_C += usb/core/hcd-pci.c +SRC_C += usb/host/ehci-pci.c +SRC_C += usb/host/ohci-hcd.c +SRC_C += usb/host/ohci-pci.c +SRC_C += usb/host/pci-quirks.c +SRC_C += usb/host/uhci-hcd.c +SRC_C += usb/host/xhci-pci.c + +SRC_CC += lx_kit/mapped_io_mem_range.cc +SRC_CC += lx_kit/pci.cc + +SRC_CC += spec/x86/platform.cc + +CC_OPT += -DCONFIG_PCI=1 +CC_OPT += -DCONFIG_USB_PCI=1 +CC_OPT += -DCONFIG_USB_EHCI_PCI=1 +CC_OPT += -DCONFIG_USB_XHCI_HCD=1 diff --git a/repos/dde_linux/src/drivers/usb_host/spec/x86_32/target.mk b/repos/dde_linux/src/drivers/usb_host/spec/x86_32/target.mk new file mode 100644 index 000000000..7f8739b0e --- /dev/null +++ b/repos/dde_linux/src/drivers/usb_host/spec/x86_32/target.mk @@ -0,0 +1,4 @@ +include $(REP_DIR)/src/drivers/usb_host/spec/x86/target.inc + +REQUIRES = x86_32 +INC_DIR += $(REP_DIR)/src/include/spec/x86_32 diff --git a/repos/dde_linux/src/drivers/usb_host/spec/x86_64/target.mk b/repos/dde_linux/src/drivers/usb_host/spec/x86_64/target.mk new file mode 100644 index 000000000..ce38422e3 --- /dev/null +++ b/repos/dde_linux/src/drivers/usb_host/spec/x86_64/target.mk @@ -0,0 +1,4 @@ +include $(REP_DIR)/src/drivers/usb_host/spec/x86/target.inc + +REQUIRES = x86_64 +INC_DIR += $(REP_DIR)/src/include/spec/x86_64 diff --git a/repos/dde_linux/src/drivers/usb_host/target.inc b/repos/dde_linux/src/drivers/usb_host/target.inc new file mode 100644 index 000000000..6bcecf274 --- /dev/null +++ b/repos/dde_linux/src/drivers/usb_host/target.inc @@ -0,0 +1,66 @@ +LX_CONTRIB_DIR := $(call select_from_ports,dde_linux)/src/drivers/usb_host +SRC_CC = main.cc lx_emul.cc raw.cc +SRC_C = dummies.c raw_driver.c +LIBS = base usb_host_include lx_kit_setjmp +CC_CXX_WARN_STRICT = + +INC_DIR += $(REP_DIR)/src/drivers/usb_host +INC_DIR += $(REP_DIR)/src/include + +# lx_kit +SRC_CC += lx_kit/printf.cc +SRC_CC += lx_kit/work.cc +SRC_CC += lx_kit/timer.cc +SRC_CC += lx_kit/scheduler.cc +SRC_CC += lx_kit/irq.cc +SRC_CC += lx_kit/malloc.cc +SRC_CC += lx_kit/env.cc + +# contrib code +SRC_C += usb/common/common.c +SRC_C += usb/core/buffer.c +SRC_C += usb/core/config.c +SRC_C += usb/core/devices.c +SRC_C += usb/core/driver.c +SRC_C += usb/core/endpoint.c +SRC_C += usb/core/file.c +SRC_C += usb/core/generic.c +SRC_C += usb/core/hcd.c +SRC_C += usb/core/hub.c +SRC_C += usb/core/message.c +SRC_C += usb/core/notify.c +SRC_C += usb/core/port.c +SRC_C += usb/core/quirks.c +SRC_C += usb/core/urb.c +SRC_C += usb/core/usb.c +SRC_C += usb/host/ehci-hcd.c +SRC_C += usb/host/xhci-dbg.c +SRC_C += usb/host/xhci-hub.c +SRC_C += usb/host/xhci-mem.c +SRC_C += usb/host/xhci-ring.c +SRC_C += usb/host/xhci.c +SRC_C += lib/ctype.c +SRC_C += lib/find_bit.c + +CC_OPT += -U__linux__ +CC_OPT += -D__KERNEL__ +CC_OPT += -DCONFIG_USB_DEVICEFS=1 +CC_OPT += -DCONFIG_HOTPLUG=1 +CC_OPT += -DCONFIG_USB_PHY=1 +CC_OPT += -DCONFIG_HAS_DMA=1 +CC_C_OPT += -std=gnu89 +CC_C_OPT += -Wno-pointer-sign +CC_C_OPT += -Wno-unused-variable +CC_C_OPT += -Wno-unused-function +CC_C_OPT += -Wno-implicit-int +CC_C_OPT += -Wno-unused-but-set-variable +CC_C_OPT += -Wno-uninitialized +CC_C_OPT += -Wno-maybe-uninitialized +CC_C_OPT += -Wno-unused-label +CC_C_OPT += -Wno-format + +vpath lib/ctype.c $(LX_CONTRIB_DIR) +vpath lib/find_bit.c $(LX_CONTRIB_DIR) +vpath %.c $(LX_CONTRIB_DIR)/drivers +vpath %.cc $(REP_DIR)/src +vpath % $(REP_DIR)/src/drivers/usb_host diff --git a/repos/dde_linux/usb_host.list b/repos/dde_linux/usb_host.list new file mode 100644 index 000000000..99351cf73 --- /dev/null +++ b/repos/dde_linux/usb_host.list @@ -0,0 +1,135 @@ +linux-x.x.x/drivers/usb/chipidea/bits.h +linux-x.x.x/drivers/usb/chipidea/ci.h +linux-x.x.x/drivers/usb/chipidea/ci_hdrc_imx.c +linux-x.x.x/drivers/usb/chipidea/ci_hdrc_imx.h +linux-x.x.x/drivers/usb/chipidea/ci_hdrc_msm.c +linux-x.x.x/drivers/usb/chipidea/ci_hdrc_usb2.c +linux-x.x.x/drivers/usb/chipidea/ci_hdrc_zevio.c +linux-x.x.x/drivers/usb/chipidea/core.c +linux-x.x.x/drivers/usb/chipidea/host.c +linux-x.x.x/drivers/usb/chipidea/host.h +linux-x.x.x/drivers/usb/chipidea/otg.c +linux-x.x.x/drivers/usb/chipidea/otg.h +linux-x.x.x/drivers/usb/chipidea/otg_fsm.h +linux-x.x.x/drivers/usb/chipidea/udc.h +linux-x.x.x/drivers/usb/chipidea/usbmisc_imx.c +linux-x.x.x/drivers/usb/common/common.c +linux-x.x.x/drivers/usb/core/buffer.c +linux-x.x.x/drivers/usb/core/config.c +linux-x.x.x/drivers/usb/core/devices.c +linux-x.x.x/drivers/usb/core/driver.c +linux-x.x.x/drivers/usb/core/endpoint.c +linux-x.x.x/drivers/usb/core/file.c +linux-x.x.x/drivers/usb/core/generic.c +linux-x.x.x/drivers/usb/core/hcd.c +linux-x.x.x/drivers/usb/core/hcd-pci.c +linux-x.x.x/drivers/usb/core/hub.h +linux-x.x.x/drivers/usb/core/hub.c +linux-x.x.x/drivers/usb/core/message.c +linux-x.x.x/drivers/usb/core/otg_whitelist.h +linux-x.x.x/drivers/usb/core/notify.c +linux-x.x.x/drivers/usb/core/port.c +linux-x.x.x/drivers/usb/core/quirks.c +linux-x.x.x/drivers/usb/core/urb.c +linux-x.x.x/drivers/usb/core/usb.h +linux-x.x.x/drivers/usb/core/usb.c +linux-x.x.x/drivers/usb/dwc3/core.c +linux-x.x.x/drivers/usb/dwc3/core.h +linux-x.x.x/drivers/usb/dwc3/debug.h +linux-x.x.x/drivers/usb/dwc3/dwc3-exynos.c +linux-x.x.x/drivers/usb/dwc3/gadget.h +linux-x.x.x/drivers/usb/dwc3/host.c +linux-x.x.x/drivers/usb/dwc3/io.h +linux-x.x.x/drivers/usb/dwc3/trace.h +linux-x.x.x/drivers/usb/host/ehci-dbg.c +linux-x.x.x/drivers/usb/host/ehci-exynos.c +linux-x.x.x/drivers/usb/host/ehci.h +linux-x.x.x/drivers/usb/host/ehci-hcd.c +linux-x.x.x/drivers/usb/host/ehci-hub.c +linux-x.x.x/drivers/usb/host/ehci-mem.c +linux-x.x.x/drivers/usb/host/ehci-omap.c +linux-x.x.x/drivers/usb/host/ehci-pci.c +linux-x.x.x/drivers/usb/host/ehci-q.c +linux-x.x.x/drivers/usb/host/ehci-sched.c +linux-x.x.x/drivers/usb/host/ehci-sysfs.c +linux-x.x.x/drivers/usb/host/ehci-timer.c +linux-x.x.x/drivers/usb/host/ohci-hcd.c +linux-x.x.x/drivers/usb/host/ohci.h +linux-x.x.x/drivers/usb/host/ohci-hub.c +linux-x.x.x/drivers/usb/host/ohci-dbg.c +linux-x.x.x/drivers/usb/host/ohci-mem.c +linux-x.x.x/drivers/usb/host/ohci-q.c +linux-x.x.x/drivers/usb/host/ohci-pci.c +linux-x.x.x/drivers/usb/host/pci-quirks.h +linux-x.x.x/drivers/usb/host/pci-quirks.c +linux-x.x.x/drivers/usb/host/uhci-debug.c +linux-x.x.x/drivers/usb/host/uhci-hcd.h +linux-x.x.x/drivers/usb/host/uhci-hcd.c +linux-x.x.x/drivers/usb/host/uhci-hub.c +linux-x.x.x/drivers/usb/host/uhci-pci.c +linux-x.x.x/drivers/usb/host/uhci-q.c +linux-x.x.x/drivers/usb/host/xhci-dbg.c +linux-x.x.x/drivers/usb/host/xhci-dbgcap.h +linux-x.x.x/drivers/usb/host/xhci-debugfs.h +linux-x.x.x/drivers/usb/host/xhci-ext-caps.h +linux-x.x.x/drivers/usb/host/xhci.h +linux-x.x.x/drivers/usb/host/xhci-hub.c +linux-x.x.x/drivers/usb/host/xhci-mem.c +linux-x.x.x/drivers/usb/host/xhci-mtk.h +linux-x.x.x/drivers/usb/host/xhci-mvebu.h +linux-x.x.x/drivers/usb/host/xhci-rcar.h +linux-x.x.x/drivers/usb/host/xhci.c +linux-x.x.x/drivers/usb/host/xhci-pci.c +linux-x.x.x/drivers/usb/host/xhci-plat.c +linux-x.x.x/drivers/usb/host/xhci-plat.h +linux-x.x.x/drivers/usb/host/xhci-ring.c +linux-x.x.x/drivers/usb/host/xhci-trace.h +linux-x.x.x/drivers/usb/phy/phy-mxs-usb.c +linux-x.x.x/include/asm-generic/atomic64.h +linux-x.x.x/include/asm-generic/bitops/__ffs.h +linux-x.x.x/include/asm-generic/bitops/__fls.h +linux-x.x.x/include/asm-generic/bitops/fls64.h +linux-x.x.x/include/asm-generic/bitops/non-atomic.h +linux-x.x.x/include/asm-generic/ioctl.h +linux-x.x.x/include/linux/ctype.h +linux-x.x.x/include/linux/extcon.h +linux-x.x.x/include/linux/hiddev.h +linux-x.x.x/include/linux/hid.h +linux-x.x.x/include/linux/input.h +linux-x.x.x/include/linux/input/mt.h +linux-x.x.x/include/linux/kfifo.h +linux-x.x.x/include/linux/list.h +linux-x.x.x/include/linux/log2.h +linux-x.x.x/include/linux/mod_devicetable.h +linux-x.x.x/include/linux/netdev_features.h +linux-x.x.x/include/linux/pci_ids.h +linux-x.x.x/include/linux/platform_data/usb-omap.h +linux-x.x.x/include/linux/power_supply.h +linux-x.x.x/include/linux/rbtree.h +linux-x.x.x/include/linux/refcount.h +linux-x.x.x/include/linux/swab.h +linux-x.x.x/include/linux/usb.h +linux-x.x.x/include/linux/usb_usual.h +linux-x.x.x/include/linux/usb/ch9.h +linux-x.x.x/include/linux/usb/chipidea.h +linux-x.x.x/include/linux/usb/cdc.h +linux-x.x.x/include/linux/usb/ehci-dbgp.h +linux-x.x.x/include/linux/usb/ehci_def.h +linux-x.x.x/include/linux/usb/hcd.h +linux-x.x.x/include/linux/io-64-nonatomic-lo-hi.h +linux-x.x.x/include/linux/usb/of.h +linux-x.x.x/include/linux/usb/otg.h +linux-x.x.x/include/linux/usb/otg-fsm.h +linux-x.x.x/include/linux/usb/phy.h +linux-x.x.x/include/linux/usb/quirks.h +linux-x.x.x/include/uapi/asm-generic/ioctl.h +linux-x.x.x/include/uapi/linux/byteorder/little_endian.h +linux-x.x.x/include/uapi/linux/pci_regs.h +linux-x.x.x/include/uapi/linux/stat.h +linux-x.x.x/include/uapi/linux/swab.h +linux-x.x.x/include/uapi/linux/usb/ch11.h +linux-x.x.x/include/uapi/linux/usb/ch9.h +linux-x.x.x/include/uapi/linux/usb/charger.h +linux-x.x.x/include/uapi/linux/usb/cdc.h +linux-x.x.x/lib/ctype.c +linux-x.x.x/lib/find_bit.c diff --git a/repos/os/run/usb_block.run b/repos/os/run/usb_block.run index 8d4c6e4cf..58d0a4eca 100644 --- a/repos/os/run/usb_block.run +++ b/repos/os/run/usb_block.run @@ -7,7 +7,7 @@ set use_qemu [have_include "power_on/qemu"] set build_components { core init drivers/timer - drivers/usb + drivers/usb_host drivers/usb_block server/report_rom test/blk/cli @@ -70,33 +70,33 @@ append config { - - + } +append config "" +append config { + - - - } + + } append_if [expr !$use_qemu] config { - - - - - - - - - - - + + + + + + + + + + + } append_if $use_qemu config { - } + } append config { - @@ -137,11 +137,12 @@ install_config $config # generic modules set boot_modules { - core init timer report_rom usb_drv usb_block_drv + core init timer report_rom usb_block_drv test-blk-cli test-blk-bench ld.lib.so } +append boot_modules [usb_host_drv_binary] lappend_if [have_spec gpio] boot_modules [gpio_drv] append_platform_drv_boot_modules