Index: uspace/drv/ohci/hc.c
===================================================================
--- uspace/drv/ohci/hc.c	(revision 19065c7cb4ff096611b7db83135551eb7fbedb69)
+++ uspace/drv/ohci/hc.c	(revision 5dfee5222840f1722deae4e46e1dfce8ed1787c5)
@@ -95,5 +95,6 @@
 }
 /*----------------------------------------------------------------------------*/
-int hc_init(hc_t *instance, uintptr_t regs, size_t reg_size, bool interrupts)
+int hc_init(hc_t *instance, ddf_fun_t *fun, ddf_dev_t *dev,
+    uintptr_t regs, size_t reg_size, bool interrupts)
 {
 	assert(instance);
Index: uspace/drv/ohci/hc.h
===================================================================
--- uspace/drv/ohci/hc.h	(revision 19065c7cb4ff096611b7db83135551eb7fbedb69)
+++ uspace/drv/ohci/hc.h	(revision 5dfee5222840f1722deae4e46e1dfce8ed1787c5)
@@ -77,5 +77,6 @@
 int hc_register_hub(hc_t *instance, ddf_fun_t *hub_fun);
 
-int hc_init(hc_t *instance, uintptr_t regs, size_t reg_size, bool interrupts);
+int hc_init(hc_t *instance, ddf_fun_t *fun, ddf_dev_t *dev,
+     uintptr_t regs, size_t reg_size, bool interrupts);
 
 void hc_start_hw(hc_t *instance);
Index: uspace/drv/ohci/main.c
===================================================================
--- uspace/drv/ohci/main.c	(revision 19065c7cb4ff096611b7db83135551eb7fbedb69)
+++ uspace/drv/ohci/main.c	(revision 5dfee5222840f1722deae4e46e1dfce8ed1787c5)
@@ -43,24 +43,5 @@
 #define NAME "ohci"
 
-/** Initializes a new ddf driver instance of OHCI hcd.
- *
- * @param[in] device DDF instance of the device to initialize.
- * @return Error code.
- */
-static int ohci_add_device(ddf_dev_t *device)
-{
-	usb_log_debug("ohci_add_device() called\n");
-	assert(device);
-
-	int ret = device_setup_ohci(device);
-	if (ret != EOK) {
-		usb_log_error("Failed to initialize OHCI driver: %s.\n",
-		    str_error(ret));
-		return ret;
-	}
-	usb_log_info("Controlling new OHCI device '%s'.\n", device->name);
-
-	return EOK;
-}
+static int ohci_add_device(ddf_dev_t *device);
 /*----------------------------------------------------------------------------*/
 static driver_ops_t ohci_driver_ops = {
@@ -72,4 +53,33 @@
 	.driver_ops = &ohci_driver_ops
 };
+/*----------------------------------------------------------------------------*/
+/** Initializes a new ddf driver instance of OHCI hcd.
+ *
+ * @param[in] device DDF instance of the device to initialize.
+ * @return Error code.
+ */
+int ohci_add_device(ddf_dev_t *device)
+{
+	usb_log_debug("ohci_add_device() called\n");
+	assert(device);
+	ohci_t *ohci = malloc(sizeof(ohci_t));
+	if (ohci == NULL) {
+		usb_log_error("Failed to allocate OHCI driver.\n");
+		return ENOMEM;
+	}
+
+	int ret = ohci_init(ohci, device);
+	if (ret != EOK) {
+		usb_log_error("Failed to initialize OHCI driver: %s.\n",
+		    str_error(ret));
+		return ret;
+	}
+//	device->driver_data = ohci;
+	hc_register_hub(&ohci->hc, ohci->rh_fun);
+
+	usb_log_info("Controlling new OHCI device `%s'.\n", device->name);
+
+	return EOK;
+}
 /*----------------------------------------------------------------------------*/
 /** Initializes global driver structures (NONE).
Index: uspace/drv/ohci/ohci.c
===================================================================
--- uspace/drv/ohci/ohci.c	(revision 19065c7cb4ff096611b7db83135551eb7fbedb69)
+++ uspace/drv/ohci/ohci.c	(revision 5dfee5222840f1722deae4e46e1dfce8ed1787c5)
@@ -44,21 +44,4 @@
 #include "iface.h"
 #include "pci.h"
-#include "hc.h"
-#include "root_hub.h"
-
-typedef struct ohci {
-	ddf_fun_t *hc_fun;
-	ddf_fun_t *rh_fun;
-
-	hc_t hc;
-	rh_t rh;
-} ohci_t;
-
-static inline ohci_t * dev_to_ohci(ddf_dev_t *dev)
-{
-	assert(dev);
-	assert(dev->driver_data);
-	return dev->driver_data;
-}
 
 /** IRQ handling callback, identifies device
@@ -70,7 +53,9 @@
 static void irq_handler(ddf_dev_t *dev, ipc_callid_t iid, ipc_call_t *call)
 {
-	hc_t *hc = &dev_to_ohci(dev)->hc;
+	assert(dev);
+	assert(dev->driver_data);
+	hc_t *hc = &((ohci_t*)dev->driver_data)->hc;
+	uint16_t status = IPC_GET_ARG1(*call);
 	assert(hc);
-	const uint16_t status = IPC_GET_ARG1(*call);
 	hc_interrupt(hc, status);
 }
@@ -86,5 +71,5 @@
 {
 	assert(fun);
-	usb_device_keeper_t *manager = &dev_to_ohci(fun->dev)->hc.manager;
+	usb_device_keeper_t *manager = &((ohci_t*)fun->dev->driver_data)->hc.manager;
 
 	usb_address_t addr = usb_device_keeper_find(manager, handle);
@@ -109,14 +94,13 @@
     ddf_fun_t *fun, devman_handle_t *handle)
 {
-	assert(fun);
-	ddf_fun_t *hc_fun = dev_to_ohci(fun->dev)->hc_fun;
-	assert(hc_fun);
-
-	if (handle != NULL)
-		*handle = hc_fun->handle;
+	assert(handle);
+	ddf_fun_t *hc_fun = ((ohci_t*)fun->dev->driver_data)->hc_fun;
+	assert(hc_fun != NULL);
+
+	*handle = hc_fun->handle;
 	return EOK;
 }
 /*----------------------------------------------------------------------------*/
-/** Root hub USB interface */
+/** This iface is generic for both RH and HC. */
 static usb_iface_t usb_iface = {
 	.get_hc_handle = usb_iface_get_hc_handle,
@@ -124,10 +108,8 @@
 };
 /*----------------------------------------------------------------------------*/
-/** Standard USB HC options (HC interface) */
 static ddf_dev_ops_t hc_ops = {
 	.interfaces[USBHC_DEV_IFACE] = &hc_iface, /* see iface.h/c */
 };
 /*----------------------------------------------------------------------------*/
-/** Standard USB RH options (RH interface) */
 static ddf_dev_ops_t rh_ops = {
 	.interfaces[USB_DEV_IFACE] = &usb_iface,
@@ -136,6 +118,6 @@
 /** Initialize hc and rh ddf structures and their respective drivers.
  *
+ * @param[in] instance OHCI structure to use.
  * @param[in] device DDF instance of the device to use.
- * @param[in] instance OHCI structure to use.
  *
  * This function does all the preparatory work for hc and rh drivers:
@@ -145,55 +127,34 @@
  *  - registers interrupt handler
  */
-int device_setup_ohci(ddf_dev_t *device)
-{
-	ohci_t *instance = malloc(sizeof(ohci_t));
-	if (instance == NULL) {
-		usb_log_error("Failed to allocate OHCI driver.\n");
-		return ENOMEM;
-	}
-
-#define CHECK_RET_DEST_FREE_RETURN(ret, message...) \
+int ohci_init(ohci_t *instance, ddf_dev_t *device)
+{
+	assert(instance);
+	instance->hc_fun = NULL;
+	instance->rh_fun = NULL;
+#define CHECK_RET_DEST_FUN_RETURN(ret, message...) \
 if (ret != EOK) { \
-	if (instance->hc_fun) { \
-		instance->hc_fun->ops = NULL; \
-		instance->hc_fun->driver_data = NULL; \
+	usb_log_error(message); \
+	if (instance->hc_fun) \
 		ddf_fun_destroy(instance->hc_fun); \
-	} \
-	if (instance->rh_fun) { \
-		instance->rh_fun->ops = NULL; \
-		instance->rh_fun->driver_data = NULL; \
+	if (instance->rh_fun) \
 		ddf_fun_destroy(instance->rh_fun); \
-	} \
-	free(instance); \
-	usb_log_error(message); \
 	return ret; \
-} else (void)0
-
-	instance->rh_fun = NULL;
-	instance->hc_fun = ddf_fun_create(device, fun_exposed, "ohci-hc");
-	int ret = instance->hc_fun ? EOK : ENOMEM;
-	CHECK_RET_DEST_FREE_RETURN(ret, "Failed to create OHCI HC function.\n");
-	instance->hc_fun->ops = &hc_ops;
-	instance->hc_fun->driver_data = &instance->hc;
-
-	instance->rh_fun = ddf_fun_create(device, fun_inner, "ohci-rh");
-	ret = instance->rh_fun ? EOK : ENOMEM;
-	CHECK_RET_DEST_FREE_RETURN(ret, "Failed to create OHCI RH function.\n");
-	instance->rh_fun->ops = &rh_ops;
-
-	uintptr_t reg_base = 0;
-	size_t reg_size = 0;
+}
+
+	uintptr_t mem_reg_base = 0;
+	size_t mem_reg_size = 0;
 	int irq = 0;
 
-	ret = pci_get_my_registers(device, &reg_base, &reg_size, &irq);
-	CHECK_RET_DEST_FREE_RETURN(ret,
+	int ret =
+	    pci_get_my_registers(device, &mem_reg_base, &mem_reg_size, &irq);
+	CHECK_RET_DEST_FUN_RETURN(ret,
 	    "Failed to get memory addresses for %" PRIun ": %s.\n",
 	    device->handle, str_error(ret));
 	usb_log_debug("Memory mapped regs at %p (size %zu), IRQ %d.\n",
-	    (void *) reg_base, reg_size, irq);
+	    (void *) mem_reg_base, mem_reg_size, irq);
 
 	bool interrupts = false;
 #ifdef CONFIG_USBHC_NO_INTERRUPTS
-	usb_log_warning("Interrupts disabled in OS config, "
+	usb_log_warning("Interrupts disabled in OS config, " \
 	    "falling back to polling.\n");
 #else
@@ -202,5 +163,5 @@
 		usb_log_warning("Failed to enable interrupts: %s.\n",
 		    str_error(ret));
-		usb_log_info("HW interrupts not available, "
+		usb_log_info("HW interrupts not available, " \
 		    "falling back to polling.\n");
 	} else {
@@ -210,12 +171,34 @@
 #endif
 
-	ret = hc_init(&instance->hc, reg_base, reg_size, interrupts);
-	CHECK_RET_DEST_FREE_RETURN(ret, "Failed(%d) to init ohci-hcd.\n", ret);
+	instance->hc_fun = ddf_fun_create(device, fun_exposed, "ohci-hc");
+	ret = (instance->hc_fun == NULL) ? ENOMEM : EOK;
+	CHECK_RET_DEST_FUN_RETURN(ret,
+	    "Failed(%d) to create HC function.\n", ret);
+
+	ret = hc_init(&instance->hc, instance->hc_fun, device,
+	    mem_reg_base, mem_reg_size, interrupts);
+	CHECK_RET_DEST_FUN_RETURN(ret, "Failed(%d) to init ohci-hcd.\n", ret);
+	instance->hc_fun->ops = &hc_ops;
+	instance->hc_fun->driver_data = &instance->hc;
+	ret = ddf_fun_bind(instance->hc_fun);
+	CHECK_RET_DEST_FUN_RETURN(ret,
+	    "Failed(%d) to bind OHCI device function: %s.\n",
+	    ret, str_error(ret));
+	ret = ddf_fun_add_to_class(instance->hc_fun, USB_HC_DDF_CLASS_NAME);
+	CHECK_RET_DEST_FUN_RETURN(ret,
+	    "Failed to add OHCI to HC class: %s.\n", str_error(ret));
+
+#undef CHECK_RET_HC_RETURN
 
 #define CHECK_RET_FINI_RETURN(ret, message...) \
 if (ret != EOK) { \
+	usb_log_error(message); \
+	if (instance->hc_fun) \
+		ddf_fun_destroy(instance->hc_fun); \
+	if (instance->rh_fun) \
+		ddf_fun_destroy(instance->rh_fun); \
 	hc_fini(&instance->hc); \
-	CHECK_RET_DEST_FREE_RETURN(ret, message); \
-} else (void)0
+	return ret; \
+}
 
 	/* It does no harm if we register this on polling */
@@ -225,20 +208,17 @@
 	    "Failed(%d) to register interrupt handler.\n", ret);
 
-	ret = ddf_fun_bind(instance->hc_fun);
+	instance->rh_fun = ddf_fun_create(device, fun_inner, "ohci-rh");
+	ret = (instance->rh_fun == NULL) ? ENOMEM : EOK;
 	CHECK_RET_FINI_RETURN(ret,
-	    "Failed(%d) to bind OHCI device function: %s.\n",
-	    ret, str_error(ret));
-
-	ret = ddf_fun_add_to_class(instance->hc_fun, USB_HC_DDF_CLASS_NAME);
-	CHECK_RET_FINI_RETURN(ret,
-	    "Failed to add OHCI to HC class: %s.\n", str_error(ret));
-
+	    "Failed(%d) to create root hub function.\n", ret);
+
+
+	instance->rh_fun->ops = &rh_ops;
+	instance->rh_fun->driver_data = NULL;
+	
 	device->driver_data = instance;
 
 	hc_start_hw(&instance->hc);
-	hc_register_hub(&instance->hc, instance->rh_fun);
 	return EOK;
-
-#undef CHECK_RET_DEST_FUN_RETURN
 #undef CHECK_RET_FINI_RETURN
 }
Index: uspace/drv/ohci/ohci.h
===================================================================
--- uspace/drv/ohci/ohci.h	(revision 19065c7cb4ff096611b7db83135551eb7fbedb69)
+++ uspace/drv/ohci/ohci.h	(revision 5dfee5222840f1722deae4e46e1dfce8ed1787c5)
@@ -38,5 +38,16 @@
 #include <ddf/driver.h>
 
-int device_setup_ohci(ddf_dev_t *device);
+#include "hc.h"
+#include "root_hub.h"
+
+typedef struct ohci {
+	ddf_fun_t *hc_fun;
+	ddf_fun_t *rh_fun;
+
+	hc_t hc;
+	rh_t rh;
+} ohci_t;
+
+int ohci_init(ohci_t *instance, ddf_dev_t *device);
 
 #endif
Index: uspace/drv/ohci/pci.c
===================================================================
--- uspace/drv/ohci/pci.c	(revision 19065c7cb4ff096611b7db83135551eb7fbedb69)
+++ uspace/drv/ohci/pci.c	(revision 5dfee5222840f1722deae4e46e1dfce8ed1787c5)
@@ -58,8 +58,5 @@
     uintptr_t *mem_reg_address, size_t *mem_reg_size, int *irq_no)
 {
-	assert(dev);
-	assert(mem_reg_address);
-	assert(mem_reg_size);
-	assert(irq_no);
+	assert(dev != NULL);
 
 	int parent_phone = devman_parent_device_connect(dev->handle,
Index: uspace/drv/ohci/root_hub.c
===================================================================
--- uspace/drv/ohci/root_hub.c	(revision 19065c7cb4ff096611b7db83135551eb7fbedb69)
+++ uspace/drv/ohci/root_hub.c	(revision 5dfee5222840f1722deae4e46e1dfce8ed1787c5)
@@ -237,5 +237,5 @@
 		return ENOMEM;
 
-	usb_log_info("OHCI root hub with %zu ports initialized.\n",
+	usb_log_info("OHCI root hub with %d ports initialized.\n",
 	    instance->port_count);
 
Index: uspace/drv/uhci-hcd/hc.c
===================================================================
--- uspace/drv/uhci-hcd/hc.c	(revision 19065c7cb4ff096611b7db83135551eb7fbedb69)
+++ uspace/drv/uhci-hcd/hc.c	(revision 5dfee5222840f1722deae4e46e1dfce8ed1787c5)
@@ -60,4 +60,5 @@
  *
  * @param[in] instance Memory place to initialize.
+ * @param[in] fun DDF function.
  * @param[in] regs Address of I/O control registers.
  * @param[in] size Size of I/O control registers.
@@ -68,5 +69,6 @@
  * interrupt fibrils.
  */
-int hc_init(hc_t *instance, void *regs, size_t reg_size, bool interrupts)
+int hc_init(hc_t *instance, ddf_fun_t *fun,
+    void *regs, size_t reg_size, bool interrupts)
 {
 	assert(reg_size >= sizeof(regs_t));
Index: uspace/drv/uhci-hcd/hc.h
===================================================================
--- uspace/drv/uhci-hcd/hc.h	(revision 19065c7cb4ff096611b7db83135551eb7fbedb69)
+++ uspace/drv/uhci-hcd/hc.h	(revision 5dfee5222840f1722deae4e46e1dfce8ed1787c5)
@@ -136,5 +136,6 @@
 } hc_t;
 
-int hc_init(hc_t *instance, void *regs, size_t reg_size, bool interupts);
+int hc_init(hc_t *instance, ddf_fun_t *fun,
+    void *regs, size_t reg_size, bool interupts);
 
 int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch);
Index: uspace/drv/uhci-hcd/main.c
===================================================================
--- uspace/drv/uhci-hcd/main.c	(revision 19065c7cb4ff096611b7db83135551eb7fbedb69)
+++ uspace/drv/uhci-hcd/main.c	(revision 5dfee5222840f1722deae4e46e1dfce8ed1787c5)
@@ -64,5 +64,11 @@
 	assert(device);
 
-	int ret = device_setup_uhci(device);
+	uhci_t *uhci = malloc(sizeof(uhci_t));
+	if (uhci == NULL) {
+		usb_log_error("Failed to allocate UHCI driver.\n");
+		return ENOMEM;
+	}
+
+	int ret = uhci_init(uhci, device);
 	if (ret != EOK) {
 		usb_log_error("Failed to initialize UHCI driver: %s.\n",
@@ -70,4 +76,6 @@
 		return ret;
 	}
+	device->driver_data = uhci;
+
 	usb_log_info("Controlling new UHCI device '%s'.\n", device->name);
 
Index: uspace/drv/uhci-hcd/uhci.c
===================================================================
--- uspace/drv/uhci-hcd/uhci.c	(revision 19065c7cb4ff096611b7db83135551eb7fbedb69)
+++ uspace/drv/uhci-hcd/uhci.c	(revision 5dfee5222840f1722deae4e46e1dfce8ed1787c5)
@@ -44,28 +44,4 @@
 #include "pci.h"
 
-#include "hc.h"
-#include "root_hub.h"
-
-/** Structure representing both functions of UHCI hc, USB host controller
- * and USB root hub */
-typedef struct uhci {
-	/** Pointer to DDF represenation of UHCI host controller */
-	ddf_fun_t *hc_fun;
-	/** Pointer to DDF represenation of UHCI root hub */
-	ddf_fun_t *rh_fun;
-
-	/** Internal driver's represenation of UHCI host controller */
-	hc_t hc;
-	/** Internal driver's represenation of UHCI root hub */
-	rh_t rh;
-} uhci_t;
-
-static inline uhci_t * dev_to_uhci(ddf_dev_t *dev)
-{
-	assert(dev);
-	assert(dev->driver_data);
-	return dev->driver_data;
-}
-/*----------------------------------------------------------------------------*/
 /** IRQ handling callback, forward status from call to diver structure.
  *
@@ -93,7 +69,8 @@
 {
 	assert(fun);
-	usb_device_keeper_t *manager = &dev_to_uhci(fun->dev)->hc.manager;
+	usb_device_keeper_t *manager =
+	    &((uhci_t*)fun->dev->driver_data)->hc.manager;
+
 	usb_address_t addr = usb_device_keeper_find(manager, handle);
-
 	if (addr < 0) {
 		return addr;
@@ -116,10 +93,9 @@
     ddf_fun_t *fun, devman_handle_t *handle)
 {
-	assert(fun);
-	ddf_fun_t *hc_fun = dev_to_uhci(fun->dev)->hc_fun;
-	assert(hc_fun);
-
-	if (handle != NULL)
-		*handle = hc_fun->handle;
+	assert(handle);
+	ddf_fun_t *hc_fun = ((uhci_t*)fun->dev->driver_data)->hc_fun;
+	assert(hc_fun != NULL);
+
+	*handle = hc_fun->handle;
 	return EOK;
 }
@@ -150,5 +126,5 @@
 static hw_res_ops_t hw_res_iface = {
 	.get_resource_list = get_resource_list,
-	.enable_interrupt = NULL,
+	.enable_interrupt = NULL
 };
 /*----------------------------------------------------------------------------*/
@@ -170,55 +146,33 @@
  *  - registers interrupt handler
  */
-int device_setup_uhci(ddf_dev_t *device)
-{
-	assert(device);
-	uhci_t *instance = malloc(sizeof(uhci_t));
-	if (instance == NULL) {
-		usb_log_error("Failed to allocate OHCI driver.\n");
-		return ENOMEM;
-	}
-
-#define CHECK_RET_DEST_FREE_RETURN(ret, message...) \
+int uhci_init(uhci_t *instance, ddf_dev_t *device)
+{
+	assert(instance);
+	instance->hc_fun = NULL;
+	instance->rh_fun = NULL;
+#define CHECK_RET_DEST_FUN_RETURN(ret, message...) \
 if (ret != EOK) { \
+	usb_log_error(message); \
 	if (instance->hc_fun) \
-		instance->hc_fun->ops = NULL; \
-		instance->hc_fun->driver_data = NULL; \
 		ddf_fun_destroy(instance->hc_fun); \
-	if (instance->rh_fun) {\
-		instance->rh_fun->ops = NULL; \
-		instance->rh_fun->driver_data = NULL; \
+	if (instance->rh_fun) \
 		ddf_fun_destroy(instance->rh_fun); \
-	} \
-	free(instance); \
-	usb_log_error(message); \
 	return ret; \
-} else (void)0
-
-	instance->rh_fun = NULL;
-	instance->hc_fun = ddf_fun_create(device, fun_exposed, "uhci-hc");
-	int ret = (instance->hc_fun == NULL) ? ENOMEM : EOK;
-	CHECK_RET_DEST_FREE_RETURN(ret, "Failed to create UHCI HC function.\n");
-	instance->hc_fun->ops = &hc_ops;
-	instance->hc_fun->driver_data = &instance->hc;
-
-	instance->rh_fun = ddf_fun_create(device, fun_inner, "uhci-rh");
-	ret = (instance->rh_fun == NULL) ? ENOMEM : EOK;
-	CHECK_RET_DEST_FREE_RETURN(ret, "Failed to create UHCI RH function.\n");
-	instance->rh_fun->ops = &rh_ops;
-	instance->rh_fun->driver_data = &instance->rh;
-
-	uintptr_t reg_base = 0;
-	size_t reg_size = 0;
+}
+
+	uintptr_t io_reg_base = 0;
+	size_t io_reg_size = 0;
 	int irq = 0;
 
-	ret = pci_get_my_registers(device, &reg_base, &reg_size, &irq);
-	CHECK_RET_DEST_FREE_RETURN(ret,
+	int ret =
+	    pci_get_my_registers(device, &io_reg_base, &io_reg_size, &irq);
+	CHECK_RET_DEST_FUN_RETURN(ret,
 	    "Failed to get I/O addresses for %" PRIun ": %s.\n",
 	    device->handle, str_error(ret));
 	usb_log_debug("I/O regs at 0x%p (size %zu), IRQ %d.\n",
-	    (void *) reg_base, reg_size, irq);
+	    (void *) io_reg_base, io_reg_size, irq);
 
 	ret = pci_disable_legacy(device);
-	CHECK_RET_DEST_FREE_RETURN(ret,
+	CHECK_RET_DEST_FUN_RETURN(ret,
 	    "Failed(%d) to disable legacy USB: %s.\n", ret, str_error(ret));
 
@@ -240,15 +194,36 @@
 #endif
 
-
-	ret = hc_init(&instance->hc, (void*)reg_base, reg_size, interrupts);
-	CHECK_RET_DEST_FREE_RETURN(ret,
+	instance->hc_fun = ddf_fun_create(device, fun_exposed, "uhci-hc");
+	ret = (instance->hc_fun == NULL) ? ENOMEM : EOK;
+	CHECK_RET_DEST_FUN_RETURN(ret,
+	    "Failed(%d) to create HC function: %s.\n", ret, str_error(ret));
+
+	ret = hc_init(&instance->hc, instance->hc_fun,
+	    (void*)io_reg_base, io_reg_size, interrupts);
+	CHECK_RET_DEST_FUN_RETURN(ret,
 	    "Failed(%d) to init uhci-hcd: %s.\n", ret, str_error(ret));
+
+	instance->hc_fun->ops = &hc_ops;
+	instance->hc_fun->driver_data = &instance->hc;
+	ret = ddf_fun_bind(instance->hc_fun);
+	CHECK_RET_DEST_FUN_RETURN(ret,
+	    "Failed(%d) to bind UHCI device function: %s.\n",
+	    ret, str_error(ret));
+	ret = ddf_fun_add_to_class(instance->hc_fun, USB_HC_DDF_CLASS_NAME);
+	CHECK_RET_DEST_FUN_RETURN(ret,
+	    "Failed to add UHCI to HC class: %s.\n", str_error(ret));
+
+#undef CHECK_RET_HC_RETURN
 
 #define CHECK_RET_FINI_RETURN(ret, message...) \
 if (ret != EOK) { \
+	usb_log_error(message); \
+	if (instance->hc_fun) \
+		ddf_fun_destroy(instance->hc_fun); \
+	if (instance->rh_fun) \
+		ddf_fun_destroy(instance->rh_fun); \
 	hc_fini(&instance->hc); \
-	CHECK_RET_DEST_FREE_RETURN(ret, message); \
 	return ret; \
-} else (void)0
+}
 
 	/* It does no harm if we register this on polling */
@@ -259,12 +234,9 @@
 	    ret, str_error(ret));
 
-	ret = ddf_fun_bind(instance->hc_fun);
-	CHECK_RET_FINI_RETURN(ret,
-	    "Failed(%d) to bind UHCI device function: %s.\n",
+	instance->rh_fun = ddf_fun_create(device, fun_inner, "uhci-rh");
+	ret = (instance->rh_fun == NULL) ? ENOMEM : EOK;
+	CHECK_RET_FINI_RETURN(ret,
+	    "Failed(%d) to create root hub function: %s.\n",
 	    ret, str_error(ret));
-
-	ret = ddf_fun_add_to_class(instance->hc_fun, USB_HC_DDF_CLASS_NAME);
-	CHECK_RET_FINI_RETURN(ret,
-	    "Failed to add UHCI to HC class: %s.\n", str_error(ret));
 
 	ret = rh_init(&instance->rh, instance->rh_fun,
@@ -273,9 +245,10 @@
 	    "Failed(%d) to setup UHCI root hub: %s.\n", ret, str_error(ret));
 
+	instance->rh_fun->ops = &rh_ops;
+	instance->rh_fun->driver_data = &instance->rh;
 	ret = ddf_fun_bind(instance->rh_fun);
 	CHECK_RET_FINI_RETURN(ret,
 	    "Failed(%d) to register UHCI root hub: %s.\n", ret, str_error(ret));
 
-	device->driver_data = instance;
 	return EOK;
 #undef CHECK_RET_FINI_RETURN
Index: uspace/drv/uhci-hcd/uhci.h
===================================================================
--- uspace/drv/uhci-hcd/uhci.h	(revision 19065c7cb4ff096611b7db83135551eb7fbedb69)
+++ uspace/drv/uhci-hcd/uhci.h	(revision 5dfee5222840f1722deae4e46e1dfce8ed1787c5)
@@ -38,5 +38,22 @@
 #include <ddf/driver.h>
 
-int device_setup_uhci(ddf_dev_t *device);
+#include "hc.h"
+#include "root_hub.h"
+
+/** Structure representing both functions of UHCI hc, USB host controller
+ * and USB root hub */
+typedef struct uhci {
+	/** Pointer to DDF represenation of UHCI host controller */
+	ddf_fun_t *hc_fun;
+	/** Pointer to DDF represenation of UHCI root hub */
+	ddf_fun_t *rh_fun;
+
+	/** Internal driver's represenation of UHCI host controller */
+	hc_t hc;
+	/** Internal driver's represenation of UHCI root hub */
+	rh_t rh;
+} uhci_t;
+
+int uhci_init(uhci_t *instance, ddf_dev_t *device);
 #endif
 /**
