Index: uspace/lib/usbhost/include/usb/host/ddf_helpers.h
===================================================================
--- uspace/lib/usbhost/include/usb/host/ddf_helpers.h	(revision d1df3818a95cee3c47bd9d726fdc58f9a8df71bc)
+++ uspace/lib/usbhost/include/usb/host/ddf_helpers.h	(revision fddffb2826e5c2083834d6285660d19d7b748821)
@@ -58,4 +58,11 @@
     interrupt_handler_t handler,
     int (*gen_irq_code)(irq_code_t *, const hw_res_list_parsed_t *));
+void ddf_hcd_gen_irq_handler(ddf_dev_t *dev, ipc_callid_t iid, ipc_call_t *call);
+int ddf_hcd_device_setup_all(ddf_dev_t *device, usb_speed_t speed, size_t bw,
+    bw_count_func_t bw_count,
+    interrupt_handler_t irq_handler,
+    int (*gen_irq_code)(irq_code_t *, const hw_res_list_parsed_t *hw_res),
+    int (*driver_init)(hcd_t *, const hw_res_list_parsed_t *, bool),
+    void (*driver_fini)(hcd_t *));
 
 #endif
Index: uspace/lib/usbhost/include/usb/host/hcd.h
===================================================================
--- uspace/lib/usbhost/include/usb/host/hcd.h	(revision d1df3818a95cee3c47bd9d726fdc58f9a8df71bc)
+++ uspace/lib/usbhost/include/usb/host/hcd.h	(revision fddffb2826e5c2083834d6285660d19d7b748821)
@@ -51,4 +51,5 @@
 typedef int (*ep_add_hook_t)(hcd_t *, endpoint_t *);
 typedef void (*ep_remove_hook_t)(hcd_t *, endpoint_t *);
+typedef void (*interrupt_hook_t)(hcd_t *, uint32_t);
 
 typedef struct {
@@ -61,4 +62,6 @@
 	/** Hook called upon removing of an endpoint. */
 	ep_remove_hook_t ep_remove_hook;
+	/** Hook to be called on device interrupt, passes ARG1 */
+	interrupt_hook_t irq_hook;
 } hc_driver_t;
 
@@ -76,5 +79,6 @@
 
 static inline void hcd_set_implementation(hcd_t *hcd, void *data,
-    schedule_hook_t schedule, ep_add_hook_t add_hook, ep_remove_hook_t rem_hook)
+    schedule_hook_t schedule, ep_add_hook_t add_hook, ep_remove_hook_t rem_hook,
+    interrupt_hook_t irq_hook)
 {
 	assert(hcd);
@@ -83,4 +87,5 @@
 	hcd->driver.ep_add_hook = add_hook;
 	hcd->driver.ep_remove_hook = rem_hook;
+	hcd->driver.irq_hook = irq_hook;
 }
 
Index: uspace/lib/usbhost/src/ddf_helpers.c
===================================================================
--- uspace/lib/usbhost/src/ddf_helpers.c	(revision d1df3818a95cee3c47bd9d726fdc58f9a8df71bc)
+++ uspace/lib/usbhost/src/ddf_helpers.c	(revision fddffb2826e5c2083834d6285660d19d7b748821)
@@ -653,5 +653,4 @@
 }
 
-
 //TODO: Move this to generic ddf?
 /** Call the parent driver with a request to enable interrupts
@@ -701,5 +700,4 @@
 }
 
-
 /** Register interrupt handler
  *
@@ -752,4 +750,101 @@
 	return irq;
 }
+
+/** IRQ handling callback, forward status from call to diver structure.
+ *
+ * @param[in] dev DDF instance of the device to use.
+ * @param[in] iid (Unused).
+ * @param[in] call Pointer to the call from kernel.
+ */
+void ddf_hcd_gen_irq_handler(ddf_dev_t *dev, ipc_callid_t iid, ipc_call_t *call)
+{
+	assert(dev);
+	hcd_t *hcd = dev_to_hcd(dev);
+	if (!hcd || !hcd->driver.irq_hook) {
+		usb_log_error("Interrupt on not yet initialized device.\n");
+		return;
+	}
+	const uint32_t status = IPC_GET_ARG1(*call);
+	hcd->driver.irq_hook(hcd, status);
+}
+/** Initialize hc and rh DDF structures and their respective drivers.
+ *
+ * @param device DDF instance of the device to use
+ * @param speed Maximum supported speed
+ * @param bw Available bandwidth (arbitrary units)
+ * @param bw_count Bandwidth computing function
+ * @param irq_handler IRQ handling function
+ * @param gen_irq_code Function to generate IRQ pseudocode
+ *                     (it needs to return used irq number)
+ * @param driver_init Function to initialize HC driver
+ * @param driver_fini Function to cleanup HC driver
+ * @return Error code
+ *
+ * This function does all the preparatory work for hc and rh drivers:
+ *  - gets device's hw resources
+ *  - attempts to enable interrupts
+ *  - registers interrupt handler
+ *  - calls driver specific initialization
+ *  - registers root hub
+ */
+int ddf_hcd_device_setup_all(ddf_dev_t *device, usb_speed_t speed, size_t bw,
+    bw_count_func_t bw_count,
+    interrupt_handler_t irq_handler,
+    int (*gen_irq_code)(irq_code_t *, const hw_res_list_parsed_t *hw_res),
+    int (*driver_init)(hcd_t *, const hw_res_list_parsed_t *, bool),
+    void (*driver_fini)(hcd_t *)
+    )
+{
+	assert(device);
+
+	hw_res_list_parsed_t hw_res;
+	int ret = hcd_ddf_get_registers(device, &hw_res);
+	if (ret != EOK) {
+		usb_log_error("Failed to get register memory addresses "
+		    "for %" PRIun ": %s.\n", ddf_dev_get_handle(device),
+		    str_error(ret));
+		return ret;
+	}
+
+	ret = hcd_ddf_setup_hc(device, speed, bw, bw_count);
+	if (ret != EOK) {
+		usb_log_error("Failed to setup generic HCD.\n");
+		hw_res_list_parsed_clean(&hw_res);
+		return ret;
+	}
+
+	const int irq = hcd_ddf_setup_interrupts(device, &hw_res, irq_handler,
+	    gen_irq_code);
+	if (irq < 0) {
+		usb_log_warning("Failed to enable interrupts: %s."
+		    " Falling back to polling.\n", str_error(irq));
+	} else {
+		usb_log_debug("Hw interrupts enabled.\n");
+	}
+
+	/* Init hw driver */
+	ret = driver_init(dev_to_hcd(device), &hw_res, !(irq < 0));
+	hw_res_list_parsed_clean(&hw_res);
+	if (ret != EOK) {
+		usb_log_error("Failed to init uhci_hcd: %s.\n", str_error(ret));
+		goto irq_unregister;
+	}
+
+	/*
+	 * Creating root hub registers a new USB device so HC
+	 * needs to be ready at this time.
+	 */
+	ret = hcd_ddf_setup_root_hub(device);
+	if (ret != EOK) {
+		usb_log_error("Failed to setup UHCI root hub: %s.\n",
+		    str_error(ret));
+		driver_fini(dev_to_hcd(device));
+irq_unregister:
+		/* Unregistering non-existent should be ok */
+		unregister_interrupt_handler(device, irq);
+		hcd_ddf_clean_hc(device);
+	}
+	return ret;
+}
 /**
  * @}
