]> Zhao Yanbai Git Server - minix.git/commitdiff
arm:adding the usbd source code.
authorKees Jongenburger <kees.jongenburger@gmail.com>
Mon, 26 May 2014 14:47:47 +0000 (16:47 +0200)
committerLionel Sambuc <lionel@minix3.org>
Mon, 28 Jul 2014 15:05:38 +0000 (17:05 +0200)
Change-Id: Ia3c50a8c5e11bf20100354de266913112cc236f9

http://gerrit.minix3.org/#/c/2689/

19 files changed:
drivers/usbd/Makefile [new file with mode: 0755]
drivers/usbd/README.txt [new file with mode: 0755]
drivers/usbd/base/earm/Makefile [new file with mode: 0755]
drivers/usbd/base/earm/usbd_earm.c [new file with mode: 0755]
drivers/usbd/base/usbd.c [new file with mode: 0755]
drivers/usbd/hcd/hcd.c [new file with mode: 0755]
drivers/usbd/hcd/hcd_common.c [new file with mode: 0755]
drivers/usbd/hcd/hcd_ddekit.c [new file with mode: 0755]
drivers/usbd/hcd/musb/musb_am335x.c [new file with mode: 0755]
drivers/usbd/hcd/musb/musb_core.c [new file with mode: 0755]
drivers/usbd/hcd/musb/musb_core.h [new file with mode: 0755]
drivers/usbd/hcd/musb/musb_regs.h [new file with mode: 0755]
drivers/usbd/include/usb/hcd_common.h [new file with mode: 0755]
drivers/usbd/include/usb/hcd_ddekit.h [new file with mode: 0755]
drivers/usbd/include/usb/hcd_interface.h [new file with mode: 0755]
drivers/usbd/include/usb/hcd_platforms.h [new file with mode: 0755]
drivers/usbd/include/usb/usb_common.h [new file with mode: 0755]
drivers/usbd/include/usb/usbd_interface.h [new file with mode: 0755]
drivers/usbd/usbd.conf [new file with mode: 0755]

diff --git a/drivers/usbd/Makefile b/drivers/usbd/Makefile
new file mode 100755 (executable)
index 0000000..61048cd
--- /dev/null
@@ -0,0 +1,11 @@
+# Makefile for usb host controllers
+
+.if ${MACHINE_ARCH} == "earm"
+
+.include <bsd.own.mk>
+
+SUBDIR= .WAIT base/earm
+
+.include <bsd.subdir.mk>
+
+.endif
diff --git a/drivers/usbd/README.txt b/drivers/usbd/README.txt
new file mode 100755 (executable)
index 0000000..e18565b
--- /dev/null
@@ -0,0 +1,16 @@
+-------------------------------------------------------------------------------
+*                           INFORMATION:                                      *
+-------------------------------------------------------------------------------
+README file for "USBD" USB host controller driver.
+
+created march-may 2014, JPEmbedded (info@jpembedded.eu)
+
+-------------------------------------------------------------------------------
+*                           KNOWN LIMITATIONS:                                *
+-------------------------------------------------------------------------------
+- Only first configuration can be selected for attached device
+- Only one device can be handled at a time, no hub functionality
+- DDEKit does not implement resource deallocation for corresponding thread
+  creation (see ddekit_thread_terminate, ddekit_thread_create) thus resources
+  are spilled
+- Driver assumes that there is no preemption for DDEKit threading
\ No newline at end of file
diff --git a/drivers/usbd/base/earm/Makefile b/drivers/usbd/base/earm/Makefile
new file mode 100755 (executable)
index 0000000..adc1615
--- /dev/null
@@ -0,0 +1,19 @@
+#
+# Makefile for the EARM USBD
+#
+
+PROG=          usbd
+SRCS=          usbd.c usbd_earm.c hcd.c hcd_common.c hcd_ddekit.c musb_am335x.c musb_core.c
+
+.PATH:         ${.CURDIR}/../ ${.CURDIR}/../../hcd ${.CURDIR}/../../hcd/musb
+
+CPPFLAGS+=     -I${.CURDIR}/../../include
+
+DPADD+=                ${LIBDDEKIT} ${LIBDDEKIT_USB_SERVER} ${LIBDEVMAN} ${LIBUSB} ${LIBMINC} ${LIBCLKCONF}
+LDADD+=                -lddekit -lddekit_usb_server -ldevman -lusb -lminc -lclkconf
+
+MAN=
+
+BINDIR?=       /usr/sbin
+
+.include <minix.service.mk>
\ No newline at end of file
diff --git a/drivers/usbd/base/earm/usbd_earm.c b/drivers/usbd/base/earm/usbd_earm.c
new file mode 100755 (executable)
index 0000000..79d8df3
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * EARM USBD setup
+ */
+
+#include <minix/board.h>
+#include <minix/syslib.h>
+
+#include <usb/hcd_platforms.h>
+#include <usb/usb_common.h>
+#include <usb/usbd_interface.h>
+
+
+/*===========================================================================*
+ *    usbd_init_hcd                                                          *
+ *===========================================================================*/
+int
+usbd_init_hcd(void)
+{
+       /* More specific platform type than just EARM */
+       static struct machine platform;
+
+       DEBUG_DUMP;
+
+       if (sys_getmachine(&platform)) {
+               USB_MSG("Getting machine type, failed");
+               return EXIT_FAILURE;
+       }
+
+       if (BOARD_IS_BB(platform.board_id)) {
+               USB_MSG("Using AM335x driver");
+               return musb_am335x_init();
+       } else {
+               USB_MSG("Only AM335x driver available");
+               return EXIT_FAILURE;
+       }
+}
+
+
+/*===========================================================================*
+ *    usbd_deinit_hcd                                                        *
+ *===========================================================================*/
+void
+usbd_deinit_hcd(void)
+{
+       /* More specific platform type than just EARM */
+       static struct machine platform;
+
+       DEBUG_DUMP;
+
+       if (sys_getmachine(&platform)) {
+               USB_MSG("Getting machine type, failed");
+               return;
+       }
+
+       if (BOARD_IS_BB(platform.board_id))
+               musb_am335x_deinit();
+       else
+               USB_MSG("Only AM335x driver available");
+}
diff --git a/drivers/usbd/base/usbd.c b/drivers/usbd/base/usbd.c
new file mode 100755 (executable)
index 0000000..7a78293
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * Entry point for USBD service, that handles USB HCDs
+ */
+
+#include <ddekit/ddekit.h>             /* ddekit_init */
+#include <ddekit/thread.h>             /* DDEKit threading */
+
+#include <minix/devman.h>              /* Initializing 'devman' */
+#include <minix/sef.h>                 /* SEF handling */
+
+#include <usb/usb_common.h>
+#include <usb/usbd_interface.h>
+
+
+/*===========================================================================*
+ *    Local declarations                                                     *
+ *===========================================================================*/
+static int usbd_sef_handler(int, sef_init_info_t *);
+static int usbd_start(void);
+static void usbd_init(void);
+static void usbd_server_thread(void *);
+
+/* TODO: No headers for these... */
+extern void ddekit_minix_wait_exit(void); /* dde.c */
+extern void ddekit_usb_server_init(void); /* usb_server.c */
+
+
+/*===========================================================================*
+ *    main                                                                   *
+ *===========================================================================*/
+int
+main(int UNUSED(argc), char * UNUSED(argv[]))
+{
+       int ret_val;
+
+       USB_MSG("Starting USBD");
+
+       /* Basic SEF,DDE,... initialization */
+       usbd_init();
+
+       /* Assume failure unless usbd_start exits gracefully */
+       ret_val = EXIT_FAILURE;
+
+       /* USB host controllers initialization */
+       if (EXIT_SUCCESS == usbd_init_hcd()) {
+
+               /* Try initializing 'devman' */
+               if (EXIT_SUCCESS == devman_init()) {
+
+                       /* Run USB driver (actually DDEKit threads)
+                        * until this call returns: */
+                       ret_val = usbd_start();
+
+               } else
+                       USB_MSG("Initializing devman, failed");
+
+               /* Clean whatever was initialized */
+               usbd_deinit_hcd();
+
+       } else
+               USB_MSG("Initializing HCDs, failed");
+
+       return ret_val;
+}
+
+
+/*===========================================================================*
+ *    usbd_sef_handler                                                       *
+ *===========================================================================*/
+static int
+usbd_sef_handler(int type, sef_init_info_t * UNUSED(info))
+{
+       DEBUG_DUMP;
+
+       switch (type) {
+               case SEF_INIT_FRESH:
+                       USB_MSG("Initializing");
+                       return EXIT_SUCCESS;
+
+               case SEF_INIT_LU:
+                       USB_MSG("Updating, not implemented");
+                       return EXIT_FAILURE;
+
+               case SEF_INIT_RESTART:
+                       USB_MSG("Restarting, not implemented");
+                       return EXIT_FAILURE;
+
+               default:
+                       USB_MSG("illegal SEF type");
+                       return EXIT_FAILURE;
+       }
+}
+
+
+/*===========================================================================*
+ *    usbd_start                                                             *
+ *===========================================================================*/
+static int
+usbd_start(void)
+{
+       DEBUG_DUMP;
+
+       /* Driver's "main loop" is within DDEKit server thread */
+       if (NULL != ddekit_thread_create(usbd_server_thread, NULL, "USBD")) {
+               /* This will lock current thread until DDEKit terminates */
+               ddekit_minix_wait_exit();
+               return EXIT_SUCCESS;
+       } else
+               return EXIT_FAILURE;
+}
+
+
+/*===========================================================================*
+ *    usbd_init                                                              *
+ *===========================================================================*/
+static void
+usbd_init(void)
+{
+       DEBUG_DUMP;
+
+       /* Set one handler for all messages */
+       sef_setcb_init_fresh(usbd_sef_handler);
+       sef_setcb_init_lu(usbd_sef_handler);
+       sef_setcb_init_restart(usbd_sef_handler);
+
+       /* Initialize DDEkit (involves sef_startup()) */
+       ddekit_init();
+}
+
+
+/*===========================================================================*
+ *    usbd_server_thread                                                     *
+ *===========================================================================*/
+static void
+usbd_server_thread(void * UNUSED(unused))
+{
+       DEBUG_DUMP;
+
+       ddekit_usb_server_init();
+}
diff --git a/drivers/usbd/hcd/hcd.c b/drivers/usbd/hcd/hcd.c
new file mode 100755 (executable)
index 0000000..e2ba409
--- /dev/null
@@ -0,0 +1,537 @@
+/*
+ * Implementation of generic HCD
+ */
+
+#include <time.h>                              /* nanosleep */
+#include <string.h>                            /* memcpy */
+
+#include <usb/hcd_common.h>
+#include <usb/hcd_ddekit.h>
+#include <usb/hcd_interface.h>
+#include <usb/usb_common.h>
+
+
+/*===========================================================================*
+ *    Local declarations                                                     *
+ *===========================================================================*/
+/* Thread to handle device logic */
+static void hcd_device_thread(void *);
+
+/* Procedure that locks device thread forever in case of error/completion */
+static void hcd_device_finish(hcd_device_state *, const char *);
+
+/* Typical USD device communication procedures */
+static int hcd_enumerate(hcd_device_state *);
+static int hcd_get_device_descriptor(hcd_device_state *);
+static int hcd_set_address(hcd_device_state *, int);
+static int hcd_get_descriptor_tree(hcd_device_state *);
+static int hcd_set_configuration(hcd_device_state *, int);
+static int hcd_handle_urb(hcd_device_state *);
+
+/* For internal use by more general methods */
+static int hcd_setup_packet(hcd_device_state *, hcd_ctrlrequest *);
+
+
+/*===========================================================================*
+ *    Local definitions                                                      *
+ *===========================================================================*/
+/* TODO: Only one device at a time */
+static hcd_device_state hcd_device[1];
+
+
+/*===========================================================================*
+ *    hcd_handle_event                                                       *
+ *===========================================================================*/
+void
+hcd_handle_event(hcd_driver_state * driver)
+{
+       hcd_device_state * this_device;
+
+       DEBUG_DUMP;
+
+       /* TODO: Finding which hcd_device is in use should be performed here */
+       this_device = &(hcd_device[0]);
+
+       /* Sometimes interrupts occur in a weird order (EP after disconnect)
+        * This helps finding ordering errors in DEBUG */
+       USB_DBG("Event: 0x%02X, state: 0x%02X",
+               driver->event, this_device->state);
+
+       /* Set what was received for device thread to use */
+       this_device->driver = driver;
+
+       /* Handle event and forward control to device thread when required */
+       switch (driver->event) {
+               case HCD_EVENT_CONNECTED:
+                       if (HCD_STATE_DISCONNECTED == this_device->state) {
+                               if (EXIT_SUCCESS != hcd_connect_device(
+                                                       this_device,
+                                                       hcd_device_thread))
+                                       USB_MSG("Device creation failed");
+                       } else
+                               USB_MSG("Device not marked as 'disconnected' "
+                                       "for 'connection' event");
+
+                       break;
+
+               case HCD_EVENT_DISCONNECTED:
+                       if (HCD_STATE_DISCONNECTED != this_device->state) {
+                               /* If connect callback was used before, call
+                                * it's equivalent to signal disconnection */
+                               if (HCD_STATE_CONNECTED == this_device->state)
+                                       hcd_disconnect_cb(this_device);
+                               hcd_disconnect_device(this_device);
+                               this_device->state = HCD_STATE_DISCONNECTED;
+                       } else
+                               USB_MSG("Device is marked as 'disconnected' "
+                                       "for 'disconnection' event");
+
+                       break;
+
+               case HCD_EVENT_ENDPOINT:
+                       /* Allow device thread to continue with it's logic */
+                       if (HCD_STATE_DISCONNECTED != this_device->state)
+                               hcd_device_continue(this_device);
+                       else
+                               USB_MSG("Device is marked as 'disconnected' "
+                                       "for 'EP' event");
+
+                       break;
+
+               default:
+                       USB_ASSERT(0, "Illegal HCD event");
+                       break;
+       }
+}
+
+
+/*===========================================================================*
+ *    hcd_device_thread                                                      *
+ *===========================================================================*/
+static void
+hcd_device_thread(void * thread_args)
+{
+       hcd_device_state * this_device;
+
+       DEBUG_DUMP;
+
+       /* Retrieve structures from generic data */
+       this_device = (hcd_device_state *)thread_args;
+
+       /* Plugged in */
+       this_device->state = HCD_STATE_CONNECTION_PENDING;
+
+       /* Enumeration sequence */
+       if (EXIT_SUCCESS != hcd_enumerate(this_device))
+               hcd_device_finish(this_device, "USB device enumeration failed");
+
+       /* Tell everyone that device was connected */
+       hcd_connect_cb(this_device);
+
+       /* Fully configured */
+       this_device->state = HCD_STATE_CONNECTED;
+
+       USB_DBG("Waiting for URBs");
+
+       /* No URB's yet */
+       this_device->urb = NULL;
+
+       /* Start handling URB's */
+       for(;;) {
+               /* Block and wait for something like 'submit URB' */
+               hcd_device_wait(this_device);
+
+               if (EXIT_SUCCESS != hcd_handle_urb(this_device))
+                       hcd_device_finish(this_device, "URB handling failed");
+       }
+
+       /* Finish device handling to avoid leaving thread */
+       hcd_device_finish(this_device, "USB device handling completed");
+}
+
+
+/*===========================================================================*
+ *    hcd_device_finish                                                      *
+ *===========================================================================*/
+static void
+hcd_device_finish(hcd_device_state * this_device, const char * finish_msg)
+{
+       DEBUG_DUMP;
+
+       USB_MSG("USB device handling finished with message: '%s'", finish_msg);
+
+       /* Lock forever */
+       for (;;) {
+               hcd_device_wait(this_device);
+               USB_MSG("Failed attempt to continue finished thread");
+       }
+}
+
+
+/*===========================================================================*
+ *    hcd_enumerate                                                          *
+ *===========================================================================*/
+static int
+hcd_enumerate(hcd_device_state * this_device)
+{
+       hcd_driver_state * d;
+
+       DEBUG_DUMP;
+
+       d = this_device->driver;
+
+       /* First let driver reset device */
+       d->reset_device(d->private_data);
+
+       /* Set parameters for further communication */
+       d->setup_device(d->private_data, HCD_DEFAULT_EP, HCD_DEFAULT_ADDR);
+
+       /* Get device descriptor */
+       if (EXIT_SUCCESS != hcd_get_device_descriptor(this_device)) {
+               USB_MSG("Failed to get device descriptor");
+               return EXIT_FAILURE;
+       }
+
+       /* TODO: dynamic device address when more devices are available */
+
+       /* Set address */
+       if (EXIT_SUCCESS != hcd_set_address(this_device, HCD_ATTACHED_ADDR)) {
+               USB_MSG("Failed to set device address");
+               return EXIT_FAILURE;
+       }
+
+       /* Set parameters for further communication */
+       d->setup_device(d->private_data, HCD_DEFAULT_EP, HCD_ATTACHED_ADDR);
+
+       /* Get other descriptors */
+       if (EXIT_SUCCESS != hcd_get_descriptor_tree(this_device)) {
+               USB_MSG("Failed to get configuration descriptor tree");
+               return EXIT_FAILURE;
+       }
+
+       /* TODO: always first configuration */
+       /* Set configuration */
+       if (EXIT_SUCCESS != hcd_set_configuration(this_device, 0x01)) {
+               USB_MSG("Failed to set configuration");
+               return EXIT_FAILURE;
+       }
+
+       USB_DBG("Enumeration completed");
+
+       return EXIT_SUCCESS;
+}
+
+
+/*===========================================================================*
+ *    hcd_get_device_descriptor                                              *
+ *===========================================================================*/
+static int
+hcd_get_device_descriptor(hcd_device_state * this_device)
+{
+       hcd_ctrlrequest setup;
+
+       DEBUG_DUMP;
+
+       /* TODO: magic numbers, no header for these */
+
+       /* Format setup packet */
+       setup.bRequestType      = 0x80;                 /* IN */
+       setup.bRequest          = 0x06;                 /* Get descriptor */
+       setup.wValue            = 0x0100;               /* Device */
+       setup.wIndex            = 0x0000;
+       setup.wLength           = sizeof(this_device->device_desc);
+
+       /* Handle formatted setup packet */
+       if (EXIT_SUCCESS != hcd_setup_packet(this_device, &setup)) {
+               USB_MSG("Handling setup packet failed");
+               return EXIT_FAILURE;
+       }
+
+       /* Put what was read in device descriptor */
+       memcpy(&(this_device->device_desc), this_device->buffer,
+               sizeof(this_device->device_desc));
+
+       /* Remember max packet size from device descriptor */
+       this_device->max_packet_size = this_device->device_desc.bMaxPacketSize;
+
+       /* Output VID/PID when debugging */
+       USB_DBG("idVendor: %02X%02X", this_device->device_desc.idVendor[1],
+                                       this_device->device_desc.idVendor[0]);
+       USB_DBG("idProduct: %02X%02X", this_device->device_desc.idProduct[1],
+                                       this_device->device_desc.idProduct[0]);
+
+       return EXIT_SUCCESS;
+}
+
+
+/*===========================================================================*
+ *    hcd_set_address                                                        *
+ *===========================================================================*/
+static int
+hcd_set_address(hcd_device_state * this_device, int address)
+{
+       hcd_ctrlrequest setup;
+
+       DEBUG_DUMP;
+
+       USB_ASSERT((address > 0) && (address < 128), "Illegal address");
+
+       /* TODO: magic numbers, no header for these */
+       setup.bRequestType      = 0x00;                 /* OUT */
+       setup.bRequest          = 0x05;                 /* Set address */
+       setup.wValue            = address;
+       setup.wIndex            = 0x0000;
+       setup.wLength           = 0x0000;
+
+       /* Handle formatted setup packet */
+       if (EXIT_SUCCESS != hcd_setup_packet(this_device, &setup)) {
+               USB_MSG("Handling setup packet failed");
+               return EXIT_FAILURE;
+       }
+
+       {
+               /* Sleep 5ms for proper addressing */
+               struct timespec nanotm = {0, HCD_NANOSLEEP_MSEC(5)};
+               nanosleep(&nanotm, NULL);
+       }
+
+       return EXIT_SUCCESS;
+}
+
+
+/*===========================================================================*
+ *    hcd_get_descriptor_tree                                                *
+ *===========================================================================*/
+static int
+hcd_get_descriptor_tree(hcd_device_state * this_device)
+{
+       hcd_config_descriptor config_descriptor;
+       hcd_ctrlrequest setup;
+       int completed;
+       int total_length;
+       int buffer_length;
+
+       DEBUG_DUMP;
+
+       /* First, ask only for configuration itself to get length info */
+       buffer_length = sizeof(config_descriptor);
+       completed = 0;
+
+       do {
+               /* TODO: configuration 0 is hard-coded
+                * but others are rarely used anyway */
+               /* TODO: magic numbers, no header for these */
+               setup.bRequestType      = 0x80;         /* IN */
+               setup.bRequest          = 0x06;         /* Get descriptor */
+               setup.wValue            = 0x0200;       /* Configuration 0 */
+               setup.wIndex            = 0x0000;
+               setup.wLength           = buffer_length;
+
+               /* Handle formatted setup packet */
+               if (EXIT_SUCCESS != hcd_setup_packet(this_device, &setup)) {
+                       USB_MSG("Handling setup packet failed");
+                       return EXIT_FAILURE;
+               }
+
+               /* If we only asked for configuration itself
+                * then ask again for other descriptors */
+               if (sizeof(config_descriptor) == buffer_length) {
+
+                       /* Put what was read in configuration descriptor */
+                       memcpy(&config_descriptor, this_device->buffer,
+                               sizeof(config_descriptor));
+
+                       /* Continue only if there is more data */
+                       total_length = config_descriptor.wTotalLength[0] +
+                               (config_descriptor.wTotalLength[1] << 8);
+
+                       if (total_length < (int)sizeof(config_descriptor)) {
+                               /* This should never happen for a fine device */
+                               USB_MSG("Illegal wTotalLength value");
+                               return EXIT_FAILURE;
+                       }
+                       else if (sizeof(config_descriptor) == total_length) {
+                               /* Nothing more was in descriptor anyway */
+                               completed = 1;
+                       }
+                       else {
+                               /* Read whatever is needed */
+                               buffer_length = total_length;
+                       }
+
+               } else {
+                       /* All data for given configuration was read */
+                       completed = 1;
+               }
+       }
+       while (!completed);
+
+       /* Create tree based on received buffer */
+       if (EXIT_SUCCESS != hcd_buffer_to_tree(this_device->buffer,
+                                               this_device->data_len,
+                                               &(this_device->config_tree))) {
+               /* This should never happen for a fine device */
+               USB_MSG("Illegal descriptor values");
+               return EXIT_FAILURE;
+       }
+
+       return EXIT_SUCCESS;
+}
+
+
+/*===========================================================================*
+ *    hcd_set_configuration                                                  *
+ *===========================================================================*/
+static int
+hcd_set_configuration(hcd_device_state * this_device, int configuration)
+{
+       hcd_ctrlrequest setup;
+
+       DEBUG_DUMP;
+
+       /* TODO: magic numbers, no header for these */
+       setup.bRequestType      = 0x00;         /* OUT */
+       setup.bRequest          = 0x09;         /* Set configuration */
+       setup.wValue            = configuration;
+       setup.wIndex            = 0x0000;
+       setup.wLength           = 0x0000;
+
+       /* Handle formatted setup packet */
+       if (EXIT_SUCCESS != hcd_setup_packet(this_device, &setup)) {
+               USB_MSG("Handling setup packet failed");
+               return EXIT_FAILURE;
+       }
+
+       return EXIT_SUCCESS;
+}
+
+
+/*===========================================================================*
+ *    hcd_handle_urb                                                         *
+ *===========================================================================*/
+static int
+hcd_handle_urb(hcd_device_state * this_device)
+{
+       DEBUG_DUMP;
+
+       USB_ASSERT(NULL != this_device->urb, "NULL URB received");
+
+       /* TODO: URB handling will be here */
+
+       /* TODO: call completion */
+       /* hcd_completion_cb */
+
+       return EXIT_SUCCESS;
+}
+
+
+/*===========================================================================*
+ *    hcd_setup_packet                                                       *
+ *===========================================================================*/
+static int
+hcd_setup_packet(hcd_device_state * this_device, hcd_ctrlrequest * setup)
+{
+       hcd_driver_state * d;
+       hcd_reg1 * current_byte;
+       int expected_len;
+       int received_len;
+
+       DEBUG_DUMP;
+
+       /* Initially... */
+       d = this_device->driver;
+       expected_len = (int)setup->wLength;
+       current_byte = this_device->buffer;
+
+       /* Send setup packet */
+       d->setup_stage(d->private_data, setup);
+
+       /* Wait for response */
+       hcd_device_wait(this_device);
+
+       /* Check response */
+       if (EXIT_SUCCESS != d->check_error(d->private_data))
+               return EXIT_FAILURE;
+
+       /* For data packets... */
+       if (expected_len > 0) {
+
+               /* TODO: magic number */
+               /* ...IN data packets */
+               if (setup->bRequestType & 0x80) {
+
+                       /* What was received until now */
+                       this_device->data_len = 0;
+
+                       do {
+                               /* Try getting data */
+                               d->in_data_stage(d->private_data);
+
+                               /* Wait for response */
+                               hcd_device_wait(this_device);
+
+                               /* Check response */
+                               if (EXIT_SUCCESS != d->check_error(
+                                                       d->private_data))
+                                       return EXIT_FAILURE;
+
+                               /* Read data received as response */
+                               received_len = d->read_data(d->private_data,
+                                                       current_byte, 0);
+
+                               /* Data reading should always yield positive
+                                * results for proper setup packet */
+                               if (received_len > 0) {
+                                       /* Try next packet */
+                                       this_device->data_len += received_len;
+                                       current_byte += received_len;
+                               } else
+                                       return EXIT_FAILURE;
+
+                       } while (expected_len > this_device->data_len);
+
+                       /* Should be exactly what we requested, no more */
+                       if (this_device->data_len != expected_len) {
+                               USB_MSG("Received more data than expected");
+                               return EXIT_FAILURE;
+                       }
+
+               } else {
+                       /* TODO: unimplemented */
+                       USB_MSG("Illegal non-zero length OUT setup packet");
+                       return EXIT_FAILURE;
+               }
+       }
+
+       /* Status stages */
+       if (setup->bRequestType & 0x80) {
+
+               /* Try confirming data receive */
+               d->out_status_stage(d->private_data);
+
+               /* Wait for response */
+               hcd_device_wait(this_device);
+
+               /* Check response */
+               if (EXIT_SUCCESS != d->check_error(d->private_data))
+                       return EXIT_FAILURE;
+
+       } else {
+
+               /* Try getting status confirmation */
+               d->in_status_stage(d->private_data);
+
+               /* Wait for response */
+               hcd_device_wait(this_device);
+
+               /* Check response */
+               if (EXIT_SUCCESS != d->check_error(d->private_data))
+                       return EXIT_FAILURE;
+
+               /* Read zero data from response to clear registers */
+               if (0 != d->read_data(d->private_data, NULL, 0))
+                       return EXIT_FAILURE;
+       }
+
+       return EXIT_SUCCESS;
+}
diff --git a/drivers/usbd/hcd/hcd_common.c b/drivers/usbd/hcd/hcd_common.c
new file mode 100755 (executable)
index 0000000..d93088d
--- /dev/null
@@ -0,0 +1,490 @@
+/*
+ * Implementation of commonly used procedures for HCD handling/initialization
+ * If possible, everything OS specific should be here
+ */
+
+#include <string.h>                    /* memset... */
+
+#include <sys/mman.h>                  /* Physical to virtual memory mapping */
+
+#include <ddekit/interrupt.h>          /* DDEKit based interrupt handling */
+
+#include <minix/clkconf.h>             /* clkconf_* */
+#include <minix/syslib.h>              /* sys_privctl */
+
+#include <usb/hcd_common.h>
+#include <usb/usb_common.h>
+
+
+/*===========================================================================*
+ *    Local prototypes                                                       *
+ *===========================================================================*/
+static int hcd_fill_configuration(hcd_reg1 *, int, hcd_configuration *, int);
+static int hcd_fill_interface(hcd_reg1 *, int, hcd_interface *, int);
+static int hcd_fill_endpoint(hcd_reg1 *, int, hcd_endpoint *, int);
+
+
+/*===========================================================================*
+ *    hcd_os_interrupt_attach                                                *
+ *===========================================================================*/
+int
+hcd_os_interrupt_attach(int irq, void (*init)(void *),
+                       void (*isr)(void *), void *priv)
+{
+       DEBUG_DUMP;
+
+       if (NULL == ddekit_interrupt_attach(irq, 0, init, isr, priv)) {
+               USB_MSG("Attaching interrupt %d failed", irq);
+               return EXIT_FAILURE;
+       }
+
+       return EXIT_SUCCESS;
+}
+
+
+/*===========================================================================*
+ *    hcd_os_interrupt_detach                                                *
+ *===========================================================================*/
+void
+hcd_os_interrupt_detach(int irq)
+{
+       DEBUG_DUMP;
+       ddekit_interrupt_detach(irq);
+}
+
+
+/*===========================================================================*
+ *    hcd_os_interrupt_enable                                                *
+ *===========================================================================*/
+void
+hcd_os_interrupt_enable(int irq)
+{
+       DEBUG_DUMP;
+       ddekit_interrupt_enable(irq);
+}
+
+
+/*===========================================================================*
+ *    hcd_os_interrupt_disable                                               *
+ *===========================================================================*/
+void
+hcd_os_interrupt_disable(int irq)
+{
+       DEBUG_DUMP;
+       ddekit_interrupt_disable(irq);
+}
+
+
+/*===========================================================================*
+ *    hcd_os_regs_init                                                       *
+ *===========================================================================*/
+void *
+hcd_os_regs_init(unsigned long base_addr, unsigned long addr_len)
+{
+       /* Memory range where we need privileged access */
+       struct minix_mem_range mr;
+
+       /* NULL unless initialization was fully completed */
+       void * virt_reg_base;
+
+       DEBUG_DUMP;
+
+       virt_reg_base = NULL;
+
+       /* Must have been set before */
+       USB_ASSERT(0 != base_addr, "Invalid base address!");
+       USB_ASSERT(0 != addr_len, "Invalid base length!");
+
+       /* Set memory range for peripheral */
+       mr.mr_base = base_addr;
+       mr.mr_limit = base_addr + addr_len;
+
+       /* Try getting access to memory range */
+       if (EXIT_SUCCESS == sys_privctl(SELF, SYS_PRIV_ADD_MEM, &mr)) {
+
+               /* And map it where we want it */
+               virt_reg_base = vm_map_phys(SELF, (void *)base_addr, addr_len);
+
+               /* Check for mapping errors to allow us returning NULL */
+               if (MAP_FAILED == virt_reg_base) {
+                       USB_MSG("Mapping memory with vm_map_phys() failed");
+                       virt_reg_base = NULL;
+               }
+
+       } else
+               USB_MSG("Acquiring memory with sys_privctl() failed");
+
+       return virt_reg_base;
+}
+
+
+/*===========================================================================*
+ *    hcd_os_regs_deinit                                                     *
+ *===========================================================================*/
+int
+hcd_os_regs_deinit(unsigned long base_addr, unsigned long addr_len)
+{
+       DEBUG_DUMP;
+
+       /* To keep USBD return value convention */
+       return (0 == vm_unmap_phys(SELF, (void*)base_addr, addr_len)) ?
+               EXIT_SUCCESS : EXIT_FAILURE;
+}
+
+
+/*===========================================================================*
+ *    hcd_os_clkconf                                                         *
+ *===========================================================================*/
+int
+hcd_os_clkconf(unsigned long clk, unsigned long mask, unsigned long value)
+{
+       DEBUG_DUMP;
+
+       /* Apparently clkconf_init may be called more than once anyway */
+       if ((0 == clkconf_init()) && (0 == clkconf_set(clk, mask, value)))
+               return EXIT_SUCCESS;
+       else
+               return EXIT_FAILURE;
+}
+
+
+/*===========================================================================*
+ *    hcd_os_clkconf_release                                                 *
+ *===========================================================================*/
+int
+hcd_os_clkconf_release(void)
+{
+       DEBUG_DUMP;
+       return clkconf_release();
+}
+
+
+/*===========================================================================*
+ *    hcd_init_device                                                        *
+ *===========================================================================*/
+int
+hcd_connect_device(hcd_device_state * this_device, hcd_thread_function funct)
+{
+       DEBUG_DUMP;
+
+       if ((NULL != this_device->lock) || (NULL != this_device->thread)) {
+               USB_MSG("Device data already allocated");
+               return EXIT_FAILURE;
+       }
+
+       if (NULL == (this_device->lock = ddekit_sem_init(0)))
+               return EXIT_FAILURE;
+
+       if (NULL == (this_device->thread = ddekit_thread_create(funct,
+                                                               this_device,
+                                                               "Device"))) {
+               ddekit_sem_deinit(this_device->lock);
+               return EXIT_FAILURE;
+       }
+
+       /* Allow device thread to work */
+       ddekit_yield();
+
+       return EXIT_SUCCESS;
+}
+
+/*===========================================================================*
+ *    hcd_deinit_device                                                      *
+ *===========================================================================*/
+void
+hcd_disconnect_device(hcd_device_state * this_device)
+{
+       DEBUG_DUMP;
+
+       hcd_tree_cleanup(&(this_device->config_tree));
+
+       /* TODO: spilled resources */
+       ddekit_thread_terminate(this_device->thread);
+       ddekit_sem_deinit(this_device->lock);
+
+       this_device->thread = NULL;
+       this_device->lock = NULL;
+}
+
+
+/*===========================================================================*
+ *    hcd_device_wait                                                        *
+ *===========================================================================*/
+void
+hcd_device_wait(hcd_device_state * this_device)
+{
+       DEBUG_DUMP;
+
+       ddekit_sem_down(this_device->lock);
+}
+
+
+/*===========================================================================*
+ *    hcd_device_continue                                                    *
+ *===========================================================================*/
+void
+hcd_device_continue(hcd_device_state * this_device)
+{
+       DEBUG_DUMP;
+
+       ddekit_sem_up(this_device->lock);
+}
+
+
+/*===========================================================================*
+ *    hcd_buffer_to_tree                                                     *
+ *===========================================================================*/
+int
+hcd_buffer_to_tree(hcd_reg1 * buf, int len, hcd_configuration * c)
+{
+       hcd_interface * i;
+       hcd_endpoint * e;
+       hcd_descriptor * desc;
+       int cfg_num;
+       int if_num;
+       int ep_num;
+
+       DEBUG_DUMP;
+
+       cfg_num = 0;
+       if_num = 0;
+       ep_num = 0;
+
+       i = NULL;
+       e = NULL;
+
+       /* Cleanup initially to NULL pointers before any allocation */
+       memset(c, 0, sizeof(*c));
+
+       while (len > (int)sizeof(*desc)) {
+               /* Check descriptor type */
+               desc = (hcd_descriptor *)buf;
+
+               if (UDESC_CONFIG == desc->bDescriptorType) {
+                       if (EXIT_SUCCESS != hcd_fill_configuration(buf, len,
+                                                               c, cfg_num++))
+                               goto PARSE_ERROR;
+
+                       if_num = 0;
+               }
+               else if (UDESC_INTERFACE == desc->bDescriptorType) {
+                       if (NULL == c->interface)
+                               goto PARSE_ERROR;
+
+                       i = &(c->interface[if_num]);
+
+                       if (EXIT_SUCCESS != hcd_fill_interface(buf, len,
+                                                               i, if_num++))
+                               goto PARSE_ERROR;
+
+                       ep_num = 0;
+               }
+               else if (UDESC_ENDPOINT == desc->bDescriptorType) {
+                       if (NULL == c->interface)
+                               goto PARSE_ERROR;
+
+                       if (NULL == i)
+                               goto PARSE_ERROR;
+
+                       e = &(i->endpoint[ep_num]);
+
+                       if (EXIT_SUCCESS != hcd_fill_endpoint(buf, len,
+                                                               e, ep_num++))
+                               goto PARSE_ERROR;
+               } else
+                       USB_DBG("Unhandled descriptor type 0x%02X",
+                               desc->bDescriptorType);
+
+               len -= desc->bLength;
+               buf += desc->bLength;
+       }
+
+       if (0 != len) {
+               USB_MSG("After parsing, some descriptor data remains");
+               goto PARSE_ERROR;
+       }
+
+       return EXIT_SUCCESS;
+
+       PARSE_ERROR:
+       hcd_tree_cleanup(c);
+       return EXIT_FAILURE;
+}
+
+
+/*===========================================================================*
+ *    hcd_tree_cleanup                                                       *
+ *===========================================================================*/
+void
+hcd_tree_cleanup(hcd_configuration * c)
+{
+       int if_idx;
+
+       DEBUG_DUMP;
+
+       /* Free if anything was allocated */
+       if (NULL != c->interface) {
+
+               USB_ASSERT(c->num_interfaces > 0, "Interface number error");
+
+               for (if_idx = 0; if_idx < c->num_interfaces; if_idx++) {
+                       if (NULL != c->interface[if_idx].endpoint) {
+                               USB_DBG("Freeing ep for interface #%d", if_idx);
+                               free(c->interface[if_idx].endpoint);
+                       }
+               }
+
+               USB_DBG("Freeing interfaces");
+               free(c->interface);
+               c->interface = NULL;
+       }
+}
+
+
+/*===========================================================================*
+ *    hcd_fill_configuration                                                 *
+ *===========================================================================*/
+static int
+hcd_fill_configuration(hcd_reg1 * buf, int len, hcd_configuration * c, int num)
+{
+       hcd_config_descriptor * desc;
+       int interfaces_size;
+
+       DEBUG_DUMP;
+
+       desc = (hcd_config_descriptor *)buf;
+
+       USB_DBG("Configuration #%d", num);
+
+       if (num > 0) {
+               USB_DBG("Only one configuration possible");
+               return EXIT_SUCCESS;
+       }
+
+       if (UDESC_CONFIG != desc->bDescriptorType)
+               return EXIT_FAILURE;
+
+       if (desc->bLength > len)
+               return EXIT_FAILURE;
+
+       if (sizeof(*desc) != desc->bLength)
+               return EXIT_FAILURE;
+
+       memcpy(&(c->descriptor), buf, sizeof(c->descriptor));
+
+       c->num_interfaces = c->descriptor.bNumInterface;
+
+       interfaces_size = c->num_interfaces * sizeof(*(c->interface));
+
+       USB_DBG("Allocating interfaces, %dB", interfaces_size);
+       c->interface = malloc(interfaces_size);
+
+       memset(c->interface, 0, interfaces_size);
+
+       /* Dump configuration in debug mode */
+       USB_DBG("<<CONFIGURATION>>");
+       USB_DBG("bLength %02X",                 desc->bLength);
+       USB_DBG("bDescriptorType %02X",         desc->bDescriptorType);
+       USB_DBG("wTotalLength %02X%02X",        desc->wTotalLength[1],
+                                               desc->wTotalLength[0]);
+       USB_DBG("bNumInterface %02X",           desc->bNumInterface);
+       USB_DBG("bConfigurationValue %02X",     desc->bConfigurationValue);
+       USB_DBG("iConfiguration %02X",          desc->iConfiguration);
+       USB_DBG("bmAttributes %02X",            desc->bmAttributes);
+       USB_DBG("bMaxPower %02X",               desc->bMaxPower);
+
+       return EXIT_SUCCESS;
+}
+
+
+/*===========================================================================*
+ *    hcd_fill_interface                                                     *
+ *===========================================================================*/
+static int
+hcd_fill_interface(hcd_reg1 * buf, int len, hcd_interface * i, int num)
+{
+       hcd_interface_descriptor * desc;
+       int endpoints_size;
+
+       DEBUG_DUMP;
+
+       desc = (hcd_interface_descriptor *)buf;
+
+       USB_DBG("Interface #%d", num);
+
+       if (UDESC_INTERFACE != desc->bDescriptorType)
+               return EXIT_FAILURE;
+
+       if (desc->bLength > len)
+               return EXIT_FAILURE;
+
+       if (sizeof(*desc) != desc->bLength)
+               return EXIT_FAILURE;
+
+       if (desc->bInterfaceNumber != num)
+               return EXIT_FAILURE;
+
+       memcpy(&(i->descriptor), buf, sizeof(i->descriptor));
+
+       i->num_endpoints = i->descriptor.bNumEndpoints;
+
+       endpoints_size = i->num_endpoints * sizeof(*(i->endpoint));
+
+       USB_DBG("Allocating endpoints, %dB", endpoints_size);
+       i->endpoint = malloc(endpoints_size);
+
+       memset(i->endpoint, 0, endpoints_size);
+
+       /* Dump interface in debug mode */
+       USB_DBG("<<INTERFACE>>");
+       USB_DBG("bLength %02X",                 desc->bLength);
+       USB_DBG("bDescriptorType %02X",         desc->bDescriptorType);
+       USB_DBG("bInterfaceNumber %02X",        desc->bInterfaceNumber);
+       USB_DBG("bAlternateSetting %02X",       desc->bAlternateSetting);
+       USB_DBG("bNumEndpoints %02X",           desc->bNumEndpoints);
+       USB_DBG("bInterfaceClass %02X",         desc->bInterfaceClass);
+       USB_DBG("bInterfaceSubClass %02X",      desc->bInterfaceSubClass);
+       USB_DBG("bInterfaceProtocol %02X",      desc->bInterfaceProtocol);
+       USB_DBG("iInterface %02X",              desc->iInterface);
+
+       return EXIT_SUCCESS;
+}
+
+
+/*===========================================================================*
+ *    hcd_fill_endpoint                                                      *
+ *===========================================================================*/
+static int
+hcd_fill_endpoint(hcd_reg1 * buf, int len, hcd_endpoint * e, int num)
+{
+       hcd_endpoint_descriptor * desc;
+
+       DEBUG_DUMP;
+
+       desc = (hcd_endpoint_descriptor *)buf;
+
+       USB_DBG("Endpoint #%d", num);
+
+       if (UDESC_ENDPOINT != desc->bDescriptorType)
+               return EXIT_FAILURE;
+
+       if (desc->bLength > len)
+               return EXIT_FAILURE;
+
+       if (sizeof(*desc) != desc->bLength)
+               return EXIT_FAILURE;
+
+       memcpy(&(e->descriptor), buf, sizeof(e->descriptor));
+
+       /* Dump endpoint in debug mode */
+       USB_DBG("<<ENDPOINT>>");
+       USB_DBG("bLength %02X",                 desc->bLength);
+       USB_DBG("bDescriptorType %02X",         desc->bDescriptorType);
+       USB_DBG("bEndpointAddress %02X",        desc->bEndpointAddress);
+       USB_DBG("bmAttributes %02X",            desc->bmAttributes);
+       USB_DBG("wMaxPacketSize %02X%02X",      desc->wMaxPacketSize[1],
+                                               desc->wMaxPacketSize[0]);
+       USB_DBG("bInterval %02X",               desc->bInterval);
+
+       return EXIT_SUCCESS;
+}
diff --git a/drivers/usbd/hcd/hcd_ddekit.c b/drivers/usbd/hcd/hcd_ddekit.c
new file mode 100755 (executable)
index 0000000..c58a747
--- /dev/null
@@ -0,0 +1,277 @@
+/*
+ * Implementation of DDEkit related calls/data
+ */
+
+#include <string.h>                            /* memset */
+
+#include <ddekit/usb.h>
+
+#include <usb/hcd_ddekit.h>
+#include <usb/usb_common.h>
+
+
+/*===========================================================================*
+ *    Local declarations                                                     *
+ *===========================================================================*/
+/*
+ * In this file "struct ddekit_usb_dev" equals "hcd_device_state"
+ * */
+struct ddekit_usb_device_id;
+struct ddekit_usb_urb;
+struct ddekit_usb_dev;
+
+/*===========================================================================*
+ *    Global definitions                                                     *
+ *===========================================================================*/
+ddekit_usb_completion_cb       completion_cb   = NULL;
+ddekit_usb_connect_cb          connect_cb      = NULL;
+ddekit_usb_disconnect_cb       disconnect_cb   = NULL;
+
+
+/*===========================================================================*
+ *    Implementation for usb_server.c                                        *
+ *===========================================================================*/
+
+/*===========================================================================*
+ *    _ddekit_usb_get_manufacturer                                           *
+ *===========================================================================*/
+char *
+_ddekit_usb_get_manufacturer(struct ddekit_usb_dev * ddev)
+{
+       static const char mfg[] = "UNKNOWN";
+       DEBUG_DUMP;
+       /* TODO: UNUSED won't work */
+       ((void)ddev);
+       return (char *)mfg;
+}
+
+
+/*===========================================================================*
+ *    _ddekit_usb_get_product                                                *
+ *===========================================================================*/
+char *
+_ddekit_usb_get_product(struct ddekit_usb_dev * ddev)
+{
+       static const char prod[] = "UNKNOWN";
+       DEBUG_DUMP;
+       /* TODO: UNUSED won't work */
+       ((void)ddev);
+       return (char *)prod;
+}
+
+
+/*===========================================================================*
+ *    _ddekit_usb_get_serial                                                 *
+ *===========================================================================*/
+char *
+_ddekit_usb_get_serial(struct ddekit_usb_dev * ddev)
+{
+       static const char serial[] = "UNKNOWN";
+       DEBUG_DUMP;
+       /* TODO: UNUSED won't work */
+       ((void)ddev);
+       return (char *)serial;
+}
+
+
+/*===========================================================================*
+ *    _ddekit_usb_get_device_desc                                            *
+ *===========================================================================*/
+struct usb_device_descriptor *
+_ddekit_usb_get_device_desc(struct ddekit_usb_dev * ddev)
+{
+       hcd_device_state * dev;
+
+       DEBUG_DUMP;
+
+       dev = (hcd_device_state *)ddev;
+
+       return (struct usb_device_descriptor *)
+               (&(dev->config_tree.descriptor));
+}
+
+
+/*===========================================================================*
+ *    _ddekit_usb_get_interface_desc                                         *
+ *===========================================================================*/
+struct usb_interface_descriptor *
+_ddekit_usb_get_interface_desc(struct ddekit_usb_dev * ddev, int inum)
+{
+       hcd_device_state * dev;
+
+       DEBUG_DUMP;
+
+       dev = (hcd_device_state *)ddev;
+
+       return (struct usb_interface_descriptor *)
+               (&(dev->config_tree.interface[inum].descriptor));
+}
+
+
+/*===========================================================================*
+ *    Implementation for <ddekit/usb.h>                                      *
+ *===========================================================================*/
+
+/*===========================================================================*
+ *    ddekit_usb_dev_set_data                                                *
+ *===========================================================================*/
+int
+ddekit_usb_dev_set_data(struct ddekit_usb_dev * dev, void * data)
+{
+       hcd_device_state * hcd_dev;
+
+       DEBUG_DUMP;
+
+       hcd_dev = (hcd_device_state *)dev;
+
+       hcd_dev->data = data;
+
+       return EXIT_SUCCESS;
+}
+
+
+/*===========================================================================*
+ *    ddekit_usb_dev_get_data                                                *
+ *===========================================================================*/
+void *
+ddekit_usb_dev_get_data(struct ddekit_usb_dev * dev)
+{
+       hcd_device_state * hcd_dev;
+
+       DEBUG_DUMP;
+
+       hcd_dev = (hcd_device_state *)dev;
+
+       return hcd_dev->data;
+}
+
+
+/* TODO: This was in header file but is not used anywhere */
+#if 0
+/*===========================================================================*
+ *    ddekit_usb_get_device_id                                               *
+ *===========================================================================*/
+void
+ddekit_usb_get_device_id(struct ddekit_usb_dev * dev,
+                       struct ddekit_usb_device_id * id)
+{
+       DEBUG_DUMP;
+       /* TODO: UNUSED won't work */
+       ((void)dev);
+       ((void)id);
+       return;
+}
+#endif
+
+
+/*===========================================================================*
+ *    ddekit_usb_submit_urb                                                  *
+ *===========================================================================*/
+int
+ddekit_usb_submit_urb(struct ddekit_usb_urb * d_urb)
+{
+       hcd_urb * urb;
+       hcd_device_state * dev;
+
+       DEBUG_DUMP;
+
+       urb = (hcd_urb *)d_urb;
+       dev = (hcd_device_state *)(urb->dev);
+
+       /* TODO: queue URB's */
+       /* Reassign and go to thread */
+       dev->urb = urb;
+       hcd_device_continue(dev);
+       dev->urb = NULL;
+
+       return EXIT_SUCCESS;
+}
+
+
+/*===========================================================================*
+ *    ddekit_usb_cancle_urb                                                  *
+ *===========================================================================*/
+int
+ddekit_usb_cancle_urb(struct ddekit_usb_urb * d_urb)
+{
+       DEBUG_DUMP;
+       /* TODO: UNUSED won't work */
+       ((void)d_urb);
+       return EXIT_SUCCESS;
+}
+
+
+/*===========================================================================*
+ *    ddekit_usb_init                                                        *
+ *===========================================================================*/
+int
+ddekit_usb_init(struct ddekit_usb_driver * drv,
+               ddekit_usb_malloc_fn * _m,
+               ddekit_usb_free_fn * _f)
+{
+       DEBUG_DUMP;
+
+       completion_cb   = drv->completion;
+       connect_cb      = drv->connect;
+       disconnect_cb   = drv->disconnect;
+
+       *_m             = malloc;
+       *_f             = free;
+
+       return EXIT_SUCCESS;
+}
+
+
+/*===========================================================================*
+ *    hcd_connect_cb                                                         *
+ *===========================================================================*/
+void hcd_connect_cb(hcd_device_state * dev)
+{
+       unsigned int if_bitmask;
+
+       DEBUG_DUMP;
+
+       /* TODO: magic numbers like in ddekit/devman */
+       /* Each bit starting from 0, represents valid interface */
+       if_bitmask = 0xFFFFFFFF >> (32 - dev->config_tree.num_interfaces);
+
+       USB_DBG("Interfaces %d, mask %08X",
+               dev->config_tree.num_interfaces,
+               if_bitmask);
+
+       connect_cb((struct ddekit_usb_dev *)dev, (int)if_bitmask);
+}
+
+
+/*===========================================================================*
+ *    hcd_disconnect_cb                                                      *
+ *===========================================================================*/
+void hcd_disconnect_cb(hcd_device_state * dev)
+{
+       DEBUG_DUMP;
+
+       disconnect_cb((struct ddekit_usb_dev *)dev);
+}
+
+
+/*===========================================================================*
+ *    hcd_completion_cb                                                      *
+ *===========================================================================*/
+void hcd_completion_cb(void * priv)
+{
+       DEBUG_DUMP;
+
+       completion_cb(priv);
+}
+
+
+/* TODO: to be removed when this is linkable */
+/*===========================================================================*
+ *    get_bp                                                                 *
+ *===========================================================================*/
+unsigned int get_bp(void)
+{
+       DEBUG_DUMP;
+
+       return EXIT_SUCCESS;
+}
diff --git a/drivers/usbd/hcd/musb/musb_am335x.c b/drivers/usbd/hcd/musb/musb_am335x.c
new file mode 100755 (executable)
index 0000000..7ea016d
--- /dev/null
@@ -0,0 +1,718 @@
+/*
+ * Implementation of whatever is hardware specific in AM335x MCU
+ */
+
+#include <string.h>                                    /* memset */
+#include <time.h>                                      /* nanosleep */
+
+#include <usb/hcd_common.h>
+#include <usb/hcd_platforms.h>
+#include <usb/hcd_interface.h>
+#include <usb/usb_common.h>
+
+#include "musb_core.h"
+
+/* TODO: BeagleBone white uses USB0 for PC connection as peripheral */
+#undef AM335X_USE_USB0
+
+
+/*===========================================================================*
+ *    AM335x base register defines                                           *
+ *===========================================================================*/
+/* Where MUSB core space starts */
+#define AM335X_MUSB_CORE0_BASE_ADDR            0x47401400u
+#define AM335X_MUSB_CORE1_BASE_ADDR            0x47401C00u
+#define AM335X_MUSB_CORE_BASE_LEN              0x400u
+
+
+/*===========================================================================*
+ *    AM335x USB specific register defines                                   *
+ *===========================================================================*/
+/* SS registers base address */
+#define AM335X_USBSS_BASE_ADDR                 0x47400000u
+
+#define AM335X_REG_REVREG                      0x000u
+#define AM335X_REG_SYSCONFIG                   0x010u
+#define AM335X_REG_IRQSTATRAW                  0x024u
+#define AM335X_REG_IRQSTAT                     0x028u
+#define AM335X_REG_IRQENABLER                  0x02Cu
+#define AM335X_REG_IRQCLEARR                   0x030u
+#define AM335X_REG_IRQDMATHOLDTX00             0x100u
+#define AM335X_REG_IRQDMATHOLDTX01             0x104u
+#define AM335X_REG_IRQDMATHOLDTX02             0x108u
+#define AM335X_REG_IRQDMATHOLDTX03             0x10Cu
+#define AM335X_REG_IRQDMATHOLDRX00             0x110u
+#define AM335X_REG_IRQDMATHOLDRX01             0x114u
+#define AM335X_REG_IRQDMATHOLDRX02             0x118u
+#define AM335X_REG_IRQDMATHOLDRX03             0x11Cu
+#define AM335X_REG_IRQDMATHOLDTX10             0x120u
+#define AM335X_REG_IRQDMATHOLDTX11             0x124u
+#define AM335X_REG_IRQDMATHOLDTX12             0x128u
+#define AM335X_REG_IRQDMATHOLDTX13             0x12Cu
+#define AM335X_REG_IRQDMATHOLDRX10             0x130u
+#define AM335X_REG_IRQDMATHOLDRX11             0x134u
+#define AM335X_REG_IRQDMATHOLDRX12             0x138u
+#define AM335X_REG_IRQDMATHOLDRX13             0x13Cu
+#define AM335X_REG_IRQDMAENABLE0               0x140u
+#define AM335X_REG_IRQDMAENABLE1               0x144u
+#define AM335X_REG_IRQFRAMETHOLDTX00           0x200u
+#define AM335X_REG_IRQFRAMETHOLDTX01           0x204u
+#define AM335X_REG_IRQFRAMETHOLDTX02           0x208u
+#define AM335X_REG_IRQFRAMETHOLDTX03           0x20Cu
+#define AM335X_REG_IRQFRAMETHOLDRX00           0x210u
+#define AM335X_REG_IRQFRAMETHOLDRX01           0x214u
+#define AM335X_REG_IRQFRAMETHOLDRX02           0x218u
+#define AM335X_REG_IRQFRAMETHOLDRX03           0x21Cu
+#define AM335X_REG_IRQFRAMETHOLDTX10           0x220u
+#define AM335X_REG_IRQFRAMETHOLDTX11           0x224u
+#define AM335X_REG_IRQFRAMETHOLDTX12           0x228u
+#define AM335X_REG_IRQFRAMETHOLDTX13           0x22Cu
+#define AM335X_REG_IRQFRAMETHOLDRX10           0x230u
+#define AM335X_REG_IRQFRAMETHOLDRX11           0x234u
+#define AM335X_REG_IRQFRAMETHOLDRX12           0x238u
+#define AM335X_REG_IRQFRAMETHOLDRX13           0x23Cu
+#define AM335X_REG_IRQFRAMEENABLE0             0x240u
+#define AM335X_REG_IRQFRAMEENABLE1             0x244u
+
+/* Length in bytes of SS registers */
+#define AM335X_USBSS_BASE_LEN                  AM335X_REG_IRQFRAMEENABLE1 + 4u
+
+/* USBx registers base addresses */
+#define AM335X_USB0_BASE_ADDR                  0x47401000u
+#define AM335X_USB1_BASE_ADDR                  0x47401800u
+
+#define AM335X_REG_USBXREV                     0x00u
+#define AM335X_REG_USBXCTRL                    0x14u
+#define AM335X_REG_USBXSTAT                    0x18u
+#define AM335X_REG_USBXIRQMSTAT                        0x20u
+#define AM335X_REG_USBXIRQSTATRAW0             0x28u
+#define AM335X_REG_USBXIRQSTATRAW1             0x2Cu
+#define AM335X_REG_USBXIRQSTAT0                        0x30u
+#define AM335X_REG_USBXIRQSTAT1                        0x34u
+#define AM335X_REG_USBXIRQENABLESET0           0x38u
+#define AM335X_REG_USBXIRQENABLESET1           0x3Cu
+#define AM335X_REG_USBXIRQENABLECLR0           0x40u
+#define AM335X_REG_USBXIRQENABLECLR1           0x44u
+#define AM335X_REG_USBXTXMODE                  0x70u
+#define AM335X_REG_USBXRXMODE                  0x74u
+#define AM335X_REG_USBXGENRNDISEP1             0x80u
+#define AM335X_REG_USBXGENRNDISEP2             0x84u
+#define AM335X_REG_USBXGENRNDISEP3             0x88u
+#define AM335X_REG_USBXGENRNDISEP4             0x8Cu
+#define AM335X_REG_USBXGENRNDISEP5             0x90u
+#define AM335X_REG_USBXGENRNDISEP6             0x94u
+#define AM335X_REG_USBXGENRNDISEP7             0x98u
+#define AM335X_REG_USBXGENRNDISEP8             0x9Cu
+#define AM335X_REG_USBXGENRNDISEP9             0xA0u
+#define AM335X_REG_USBXGENRNDISEP10            0xA4u
+#define AM335X_REG_USBXGENRNDISEP11            0xA8u
+#define AM335X_REG_USBXGENRNDISEP12            0xACu
+#define AM335X_REG_USBXGENRNDISEP13            0xB0u
+#define AM335X_REG_USBXGENRNDISEP14            0xB4u
+#define AM335X_REG_USBXGENRNDISEP15            0xB8u
+#define AM335X_REG_USBXAUTOREQ                 0xD0u
+#define AM335X_REG_USBXSRPFIXTIME              0xD4u
+#define AM335X_REG_USBX_TDOWN                  0xD8u
+#define AM335X_REG_USBXUTMI                    0xE0u
+#define AM335X_REG_USBXMGCUTMILB               0xE4u
+#define AM335X_REG_USBXMODE                    0xE8u
+
+/* Values to be set */
+#define AM335X_VAL_USBXCTRL_SOFT_RESET         HCD_BIT(0)
+#define AM335X_VAL_USBXCTRL_UINT               HCD_BIT(3)
+
+#define AM335X_VAL_USBXMODE_IDDIG_MUX          HCD_BIT(7)
+#define AM335X_VAL_USBXMODE_IDDIG              HCD_BIT(8)
+
+#define AM335X_VAL_USBXIRQENABLEXXX0_EP0       HCD_BIT(0)
+#define AM335X_VAL_USBXIRQENABLEXXX0_TX_EP1    HCD_BIT(1)
+#define AM335X_VAL_USBXIRQENABLEXXX0_TX_EP2    HCD_BIT(2)
+#define AM335X_VAL_USBXIRQENABLEXXX0_TX_EP3    HCD_BIT(3)
+#define AM335X_VAL_USBXIRQENABLEXXX0_TX_EP4    HCD_BIT(4)
+#define AM335X_VAL_USBXIRQENABLEXXX0_TX_EP5    HCD_BIT(5)
+#define AM335X_VAL_USBXIRQENABLEXXX0_TX_EP6    HCD_BIT(6)
+#define AM335X_VAL_USBXIRQENABLEXXX0_TX_EP7    HCD_BIT(7)
+#define AM335X_VAL_USBXIRQENABLEXXX0_TX_EP8    HCD_BIT(8)
+#define AM335X_VAL_USBXIRQENABLEXXX0_TX_EP9    HCD_BIT(9)
+#define AM335X_VAL_USBXIRQENABLEXXX0_TX_EP10   HCD_BIT(10)
+#define AM335X_VAL_USBXIRQENABLEXXX0_TX_EP11   HCD_BIT(11)
+#define AM335X_VAL_USBXIRQENABLEXXX0_TX_EP12   HCD_BIT(12)
+#define AM335X_VAL_USBXIRQENABLEXXX0_TX_EP13   HCD_BIT(13)
+#define AM335X_VAL_USBXIRQENABLEXXX0_TX_EP14   HCD_BIT(14)
+#define AM335X_VAL_USBXIRQENABLEXXX0_TX_EP15   HCD_BIT(15)
+#define AM335X_VAL_USBXIRQENABLEXXX0_RX_EP1    HCD_BIT(17)
+#define AM335X_VAL_USBXIRQENABLEXXX0_RX_EP2    HCD_BIT(18)
+#define AM335X_VAL_USBXIRQENABLEXXX0_RX_EP3    HCD_BIT(19)
+#define AM335X_VAL_USBXIRQENABLEXXX0_RX_EP4    HCD_BIT(20)
+#define AM335X_VAL_USBXIRQENABLEXXX0_RX_EP5    HCD_BIT(21)
+#define AM335X_VAL_USBXIRQENABLEXXX0_RX_EP6    HCD_BIT(22)
+#define AM335X_VAL_USBXIRQENABLEXXX0_RX_EP7    HCD_BIT(23)
+#define AM335X_VAL_USBXIRQENABLEXXX0_RX_EP8    HCD_BIT(24)
+#define AM335X_VAL_USBXIRQENABLEXXX0_RX_EP9    HCD_BIT(25)
+#define AM335X_VAL_USBXIRQENABLEXXX0_RX_EP10   HCD_BIT(26)
+#define AM335X_VAL_USBXIRQENABLEXXX0_RX_EP11   HCD_BIT(27)
+#define AM335X_VAL_USBXIRQENABLEXXX0_RX_EP12   HCD_BIT(28)
+#define AM335X_VAL_USBXIRQENABLEXXX0_RX_EP13   HCD_BIT(29)
+#define AM335X_VAL_USBXIRQENABLEXXX0_RX_EP14   HCD_BIT(30)
+#define AM335X_VAL_USBXIRQENABLEXXX0_RX_EP15   HCD_BIT(31)
+
+#define AM335X_VAL_USBXIRQENABLEXXX1_SUSPEND           HCD_BIT(0)
+#define AM335X_VAL_USBXIRQENABLEXXX1_RESUME            HCD_BIT(1)
+#define AM335X_VAL_USBXIRQENABLEXXX1_RESET_BABBLE      HCD_BIT(2)
+#define AM335X_VAL_USBXIRQENABLEXXX1_SOF               HCD_BIT(3)
+#define AM335X_VAL_USBXIRQENABLEXXX1_CONNECTED         HCD_BIT(4)
+#define AM335X_VAL_USBXIRQENABLEXXX1_DISCONNECTED      HCD_BIT(5)
+#define AM335X_VAL_USBXIRQENABLEXXX1_SRP               HCD_BIT(6)
+#define AM335X_VAL_USBXIRQENABLEXXX1_VBUS              HCD_BIT(7)
+#define AM335X_VAL_USBXIRQENABLEXXX1_DRVVBUS           HCD_BIT(8)
+#define AM335X_VAL_USBXIRQENABLEXXX1_GENERIC           HCD_BIT(9)
+
+#define AM335X_VAL_USBXIRQSTAT1_SUSPEND                HCD_BIT(0)
+#define AM335X_VAL_USBXIRQSTAT1_RESUME         HCD_BIT(1)
+#define AM335X_VAL_USBXIRQSTAT1_RESET_BABBLE   HCD_BIT(2)
+#define AM335X_VAL_USBXIRQSTAT1_SOF            HCD_BIT(3)
+#define AM335X_VAL_USBXIRQSTAT1_CONNECTED      HCD_BIT(4)
+#define AM335X_VAL_USBXIRQSTAT1_DISCONNECTED   HCD_BIT(5)
+#define AM335X_VAL_USBXIRQSTAT1_SRP            HCD_BIT(6)
+#define AM335X_VAL_USBXIRQSTAT1_VBUS           HCD_BIT(7)
+#define AM335X_VAL_USBXIRQSTAT1_DRVVBUS                HCD_BIT(8)
+#define AM335X_VAL_USBXIRQSTAT1_GENERIC                HCD_BIT(9)
+
+/* Length in bytes of USBx registers */
+#define AM335X_USBX_BASE_LEN                   AM335X_REG_USBXMODE + 4u
+
+/* Helpers for interrupt clearing */
+#define CLEAR_IRQ0(irq0_bit)   HCD_WR4(r, AM335X_REG_USBXIRQSTAT0, (irq0_bit))
+#define CLEAR_IRQ1(irq1_bit)   HCD_WR4(r, AM335X_REG_USBXIRQSTAT1, (irq1_bit))
+
+
+/*===========================================================================*
+ *    AM335x clocking register defines                                       *
+ *===========================================================================*/
+/* Clock module registers offsets */
+#define AM335X_CM_PER_BASE_OFFSET      0x00u
+#define AM335X_REG_CM_PER_USB0_CLKCTRL (AM335X_CM_PER_BASE_OFFSET + 28u)
+
+/* Possible values to be set */
+#define AM335X_VAL_CM_PER_USB0_CLKCTRL_MODULEMODE_ENABLE       0x2u
+#define AM335X_CLKCONF_FULL_VAL                                        0xFFFFFFFFu
+
+
+/*===========================================================================*
+ *    AM335x USB configuration structures                                    *
+ *===========================================================================*/
+#define AM335X_USBSS_IRQ                       17
+#define AM335X_USB0_IRQ                                18
+#define AM335X_USB1_IRQ                                19
+
+/* Hardware configuration values specific to AM335X USBSS (USB Subsystem) */
+typedef struct am335x_ss_config {
+
+       void * regs; /* Points to beginning of memory mapped register space */
+}
+am335x_ss_config;
+
+/* Hardware configuration values specific to AM335X USB(0,1) OTG */
+typedef struct am335x_usbX_config {
+
+       void * regs; /* Points to beginning of memory mapped register space */
+}
+am335x_usbX_config;
+
+/* Private data for AM335X's IRQ thread */
+typedef struct am335x_irq_private {
+
+       int usb_num; /* Number of currently handled controller (0, 1) */
+}
+am335x_irq_private;
+
+/* Single MUSB peripheral information */
+typedef struct am335x_controller {
+
+       am335x_irq_private      priv;
+       am335x_usbX_config      usb;
+       musb_core_config        core;
+       hcd_driver_state        driver;
+}
+am335x_controller;
+
+#define AM335X_NUM_USB_CONTROLLERS     2
+#define AM335X_USB0                    0
+#define AM335X_USB1                    1
+
+/* Configuration values specific to AM335X... */
+typedef struct am335x_config {
+
+       am335x_ss_config        ss;
+       am335x_controller       ctrl[AM335X_NUM_USB_CONTROLLERS];
+}
+am335x_config;
+
+/* ...and their current holder */
+static am335x_config am335x;
+
+
+/*===========================================================================*
+ *    Local declarations                                                     *
+ *===========================================================================*/
+/* Basic functionality */
+static int musb_am335x_internal_init(void);
+static void musb_am335x_internal_deinit(void);
+
+/* Interrupt related */
+static void musb_am335x_irq_init(void *); /* TODO: required by DDEKit */
+static void musb_am335x_usbss_isr(void *);
+static void musb_am335x_usbx_isr(void *);
+
+/* Configuration helpers */
+static void musb_am335x_usb_reset(int);
+static void musb_am335x_otg_enable(int);
+
+
+/*===========================================================================*
+ *    musb_am335x_init                                                       *
+ *===========================================================================*/
+int
+musb_am335x_init(void)
+{
+       am335x_controller * ctrl;
+
+       DEBUG_DUMP;
+
+       /* Initial cleanup */
+       memset(&am335x, 0, sizeof(am335x));
+
+       /* These registers are specific to AM335X so they are mapped here */
+       /* -------------------------------------------------------------- */
+       /* USBSS -------------------------------------------------------- */
+       /* -------------------------------------------------------------- */
+
+       /* Map memory for USBSS */
+       am335x.ss.regs = hcd_os_regs_init(AM335X_USBSS_BASE_ADDR,
+                                       AM335X_USBSS_BASE_LEN);
+
+       if (NULL == am335x.ss.regs)
+               return EXIT_FAILURE;
+
+       /* Attach IRQ to number */
+       if (EXIT_SUCCESS != hcd_os_interrupt_attach(AM335X_USBSS_IRQ,
+                                               musb_am335x_irq_init,
+                                               musb_am335x_usbss_isr,
+                                               NULL))
+               return EXIT_FAILURE;
+
+#ifdef AM335X_USE_USB0
+       /* -------------------------------------------------------------- */
+       /* USB0 --------------------------------------------------------- */
+       /* -------------------------------------------------------------- */
+       {
+               ctrl = &(am335x.ctrl[AM335X_USB0]);
+
+               /* IRQ thread private data */
+               ctrl->priv.usb_num = AM335X_USB0;
+
+               /* MUSB core addresses for later registering */
+               ctrl->core.regs = hcd_os_regs_init(AM335X_MUSB_CORE0_BASE_ADDR,
+                                               AM335X_MUSB_CORE_BASE_LEN);
+
+               if (NULL == ctrl->core.regs)
+                       return EXIT_FAILURE;
+
+               /* Map AM335X USB0 specific addresses */
+               ctrl->usb.regs = hcd_os_regs_init(AM335X_USB0_BASE_ADDR,
+                                               AM335X_USBX_BASE_LEN);
+
+               if (NULL == ctrl->usb.regs)
+                       return EXIT_FAILURE;
+
+               /* Attach IRQ to number */
+               if (EXIT_SUCCESS != hcd_os_interrupt_attach(AM335X_USB0_IRQ,
+                                                       musb_am335x_irq_init,
+                                                       musb_am335x_usbx_isr,
+                                                       &(ctrl->priv)))
+                       return EXIT_FAILURE;
+
+               /* Initialize HCD driver */
+               ctrl->driver.private_data = &(ctrl->core);
+               ctrl->driver.setup_device = musb_setup_device;
+               ctrl->driver.reset_device = musb_reset_device;
+               ctrl->driver.setup_stage = musb_setup_stage;
+               ctrl->driver.in_data_stage = musb_in_data_stage;
+               ctrl->driver.out_data_stage = musb_out_data_stage;
+               ctrl->driver.in_status_stage = musb_in_status_stage;
+               ctrl->driver.out_status_stage = musb_out_status_stage;
+               ctrl->driver.read_data = musb_read_data;
+               ctrl->driver.check_error = musb_check_error;
+       }
+#endif
+
+       /* -------------------------------------------------------------- */
+       /* USB1 --------------------------------------------------------- */
+       /* -------------------------------------------------------------- */
+       {
+               ctrl = &(am335x.ctrl[AM335X_USB1]);
+
+               /* IRQ thread private data */
+               ctrl->priv.usb_num = AM335X_USB1;
+
+               /* MUSB core addresses for later registering */
+               ctrl->core.regs = hcd_os_regs_init(AM335X_MUSB_CORE1_BASE_ADDR,
+                                               AM335X_MUSB_CORE_BASE_LEN);
+
+               if (NULL == ctrl->core.regs)
+                       return EXIT_FAILURE;
+
+               /* Map AM335X USB1 specific addresses */
+               ctrl->usb.regs = hcd_os_regs_init(AM335X_USB1_BASE_ADDR,
+                                               AM335X_USBX_BASE_LEN);
+
+               if (NULL == ctrl->usb.regs)
+                       return EXIT_FAILURE;
+
+               /* Attach IRQ to number */
+               if (EXIT_SUCCESS != hcd_os_interrupt_attach(AM335X_USB1_IRQ,
+                                                       musb_am335x_irq_init,
+                                                       musb_am335x_usbx_isr,
+                                                       &(ctrl->priv)))
+                       return EXIT_FAILURE;
+
+               /* Initialize HCD driver */
+               ctrl->driver.private_data = &(ctrl->core);
+               ctrl->driver.setup_device = musb_setup_device;
+               ctrl->driver.reset_device = musb_reset_device;
+               ctrl->driver.setup_stage = musb_setup_stage;
+               ctrl->driver.in_data_stage = musb_in_data_stage;
+               ctrl->driver.out_data_stage = musb_out_data_stage;
+               ctrl->driver.in_status_stage = musb_in_status_stage;
+               ctrl->driver.out_status_stage = musb_out_status_stage;
+               ctrl->driver.read_data = musb_read_data;
+               ctrl->driver.check_error = musb_check_error;
+       }
+
+       return musb_am335x_internal_init();
+}
+
+
+/*===========================================================================*
+ *    musb_am335x_deinit                                                     *
+ *===========================================================================*/
+void
+musb_am335x_deinit(void)
+{
+       DEBUG_DUMP;
+
+       musb_am335x_internal_deinit();
+
+       /* Release maps if anything was assigned */
+#ifdef AM335X_USE_USB0
+       if (NULL != am335x.ctrl[AM335X_USB0].usb.regs)
+               if (EXIT_SUCCESS != hcd_os_regs_deinit(AM335X_USB0_BASE_ADDR,
+                                                       AM335X_USBX_BASE_LEN))
+                       USB_MSG("Failed to release USB0 OTG mapping");
+
+       if (NULL != am335x.ctrl[AM335X_USB0].core.regs)
+               if (EXIT_SUCCESS != hcd_os_regs_deinit(
+                                               AM335X_MUSB_CORE0_BASE_ADDR,
+                                               AM335X_MUSB_CORE_BASE_LEN))
+                       USB_MSG("Failed to release USB0 core mapping");
+#endif
+       if (NULL != am335x.ctrl[AM335X_USB1].usb.regs)
+               if (EXIT_SUCCESS != hcd_os_regs_deinit(AM335X_USB1_BASE_ADDR,
+                                                       AM335X_USBX_BASE_LEN))
+                       USB_MSG("Failed to release USB1 OTG mapping");
+
+       if (NULL != am335x.ctrl[AM335X_USB1].core.regs)
+               if (EXIT_SUCCESS != hcd_os_regs_deinit(
+                                               AM335X_MUSB_CORE1_BASE_ADDR,
+                                               AM335X_MUSB_CORE_BASE_LEN))
+                       USB_MSG("Failed to release USB1 core mapping");
+
+       if (NULL != am335x.ss.regs)
+               if (EXIT_SUCCESS != hcd_os_regs_deinit(AM335X_USBSS_BASE_ADDR,
+                                                       AM335X_USBSS_BASE_LEN))
+                       USB_MSG("Failed to release USBSS mapping");
+}
+
+
+/*===========================================================================*
+ *    musb_am335x_internal_init                                              *
+ *===========================================================================*/
+static int
+musb_am335x_internal_init(void)
+{
+       DEBUG_DUMP;
+
+       /* Configure clocking */
+       if (hcd_os_clkconf(AM335X_REG_CM_PER_USB0_CLKCTRL,
+                       AM335X_VAL_CM_PER_USB0_CLKCTRL_MODULEMODE_ENABLE,
+                       AM335X_CLKCONF_FULL_VAL))
+               return EXIT_FAILURE;
+
+       /* TODO: time to stabilize? */
+       {
+               /* Sleep 25ms */
+               struct timespec nanotm = {0, HCD_NANOSLEEP_MSEC(25)};
+               nanosleep(&nanotm, NULL);
+       }
+
+       /* Read and dump revision register */
+       USB_MSG("Revision (REVREG): %08X",
+               (unsigned int)HCD_RD4(am335x.ss.regs, AM335X_REG_REVREG));
+
+       /* Allow OS to handle previously configured USBSS interrupts */
+       hcd_os_interrupt_enable(AM335X_USBSS_IRQ);
+
+#ifdef AM335X_USE_USB0
+       /* Reset controllers so we get default register values */
+       musb_am335x_usb_reset(AM335X_USB0);
+       /* Allow OS to handle previously configured USB0 interrupts */
+       hcd_os_interrupt_enable(AM335X_USB0_IRQ);
+       /* Enable whatever necessary for OTG part of controller */
+       musb_am335x_otg_enable(AM335X_USB0);
+       /* Configure control endpoint EP0 */
+       musb_ep0_config(&(am335x.ctrl[AM335X_USB0].core));
+       /* Start actual MUSB core */
+       musb_core_start(&(am335x.ctrl[AM335X_USB0].core));
+#endif
+
+       /* Reset controllers so we get default register values */
+       musb_am335x_usb_reset(AM335X_USB1);
+       /* Allow OS to handle previously configured USB1 interrupts */
+       hcd_os_interrupt_enable(AM335X_USB1_IRQ);
+       /* Enable whatever necessary for OTG part of controller */
+       musb_am335x_otg_enable(AM335X_USB1);
+       /* Configure control endpoint EP0 */
+       musb_ep0_config(&(am335x.ctrl[AM335X_USB1].core));
+       /* Start actual MUSB core */
+       musb_core_start(&(am335x.ctrl[AM335X_USB1].core));
+
+       return EXIT_SUCCESS;
+}
+
+
+/*===========================================================================*
+ *    musb_am335x_internal_deinit                                            *
+ *===========================================================================*/
+static void
+musb_am335x_internal_deinit(void)
+{
+       DEBUG_DUMP;
+
+       /* Disable all interrupts */
+       hcd_os_interrupt_disable(AM335X_USBSS_IRQ);
+#ifdef AM335X_USE_USB0
+       hcd_os_interrupt_disable(AM335X_USB0_IRQ);
+#endif
+       hcd_os_interrupt_disable(AM335X_USB1_IRQ);
+
+       /* Stop core */
+#ifdef AM335X_USE_USB0
+       musb_core_stop(&(am335x.ctrl[AM335X_USB0].core));
+#endif
+       musb_core_stop(&(am335x.ctrl[AM335X_USB1].core));
+
+       /* Every clkconf call should have corresponding release */
+       hcd_os_clkconf_release();
+}
+
+
+/*===========================================================================*
+ *    musb_am335x_irq_init                                                   *
+ *===========================================================================*/
+static void
+musb_am335x_irq_init(void * UNUSED(unused))
+{
+       DEBUG_DUMP;
+}
+
+
+/*===========================================================================*
+ *    musb_am335x_usbss_isr                                                  *
+ *===========================================================================*/
+static void
+musb_am335x_usbss_isr(void * UNUSED(data))
+{
+       void * r;
+       hcd_reg4 irqstat;
+
+       DEBUG_DUMP;
+
+       r = am335x.ss.regs;
+
+       irqstat = HCD_RD4(r, AM335X_REG_IRQSTAT);
+
+       USB_DBG("AM335X_REG_IRQSTAT = %X", (unsigned int)irqstat);
+
+       /* Write to clear interrupt */
+       HCD_WR4(r, AM335X_REG_IRQSTAT, irqstat);
+}
+
+
+/*===========================================================================*
+ *    musb_am335x_usbx_isr                                                   *
+ *===========================================================================*/
+static void
+musb_am335x_usbx_isr(void * data)
+{
+       void * r;
+       hcd_driver_state * driver;
+       hcd_reg4 irqstat0;
+       hcd_reg4 irqstat1;
+       int usb_num;
+
+       DEBUG_DUMP;
+
+       /* Prepare locals based on USB controller number for this interrupt */
+       usb_num = ((am335x_irq_private*)data)->usb_num;
+       r = am335x.ctrl[usb_num].usb.regs;
+       driver = &(am335x.ctrl[usb_num].driver);
+
+       /* Read, handle and clean interrupts */
+       irqstat0 = HCD_RD4(r, AM335X_REG_USBXIRQSTAT0);
+       irqstat1 = HCD_RD4(r, AM335X_REG_USBXIRQSTAT1);
+
+       /* TODO: priority of interrupts */
+       if (irqstat1 & AM335X_VAL_USBXIRQSTAT1_DRVVBUS) {
+               USB_DBG("DRVVBUS level changed");
+               CLEAR_IRQ1(AM335X_VAL_USBXIRQSTAT1_DRVVBUS);
+               return;
+       }
+
+       if (irqstat1 & AM335X_VAL_USBXIRQENABLEXXX1_CONNECTED) {
+               USB_DBG("Device connected");
+               CLEAR_IRQ1(AM335X_VAL_USBXIRQENABLEXXX1_CONNECTED);
+               driver->event = HCD_EVENT_CONNECTED;
+               driver->subevent = HCD_SUBEVENT_NONE;
+               hcd_handle_event(driver);
+               return;
+       }
+
+       if (irqstat1 & AM335X_VAL_USBXIRQENABLEXXX1_DISCONNECTED) {
+               USB_DBG("Device disconnected");
+               CLEAR_IRQ1(AM335X_VAL_USBXIRQENABLEXXX1_DISCONNECTED);
+               driver->event = HCD_EVENT_DISCONNECTED;
+               driver->subevent = HCD_SUBEVENT_NONE;
+               hcd_handle_event(driver);
+               return;
+       }
+
+       if (irqstat0 & 0x01) {
+               USB_DBG("EP0 interrupt");
+               CLEAR_IRQ0(0x01);
+               driver->event = HCD_EVENT_ENDPOINT;
+               driver->subevent = HCD_SUBEVENT_EP0;
+               hcd_handle_event(driver);
+               return;
+       }
+
+       if (irqstat1 & AM335X_VAL_USBXIRQENABLEXXX1_SUSPEND) {
+               USB_DBG("Unhandled SUSPEND IRQ");
+               CLEAR_IRQ1(AM335X_VAL_USBXIRQENABLEXXX1_SUSPEND);
+               return;
+       }
+
+       if (irqstat1 & AM335X_VAL_USBXIRQENABLEXXX1_RESUME) {
+               USB_DBG("Unhandled RESUME IRQ");
+               CLEAR_IRQ1(AM335X_VAL_USBXIRQENABLEXXX1_RESUME);
+               return;
+       }
+
+       if (irqstat1 & AM335X_VAL_USBXIRQENABLEXXX1_RESET_BABBLE) {
+               USB_DBG("Unhandled RESET/BABBLE IRQ");
+               CLEAR_IRQ1(AM335X_VAL_USBXIRQENABLEXXX1_RESET_BABBLE);
+               return;
+       }
+
+       if (irqstat1 & AM335X_VAL_USBXIRQENABLEXXX1_SOF) {
+               USB_DBG("Unhandled SOF IRQ");
+               CLEAR_IRQ1(AM335X_VAL_USBXIRQENABLEXXX1_SOF);
+               return;
+       }
+
+       if (irqstat1 & AM335X_VAL_USBXIRQENABLEXXX1_SRP) {
+               USB_DBG("Unhandled SRP IRQ");
+               CLEAR_IRQ1(AM335X_VAL_USBXIRQENABLEXXX1_SRP);
+               return;
+       }
+
+       if (irqstat1 & AM335X_VAL_USBXIRQENABLEXXX1_VBUS) {
+               USB_DBG("Unhandled VBUS IRQ");
+               CLEAR_IRQ1(AM335X_VAL_USBXIRQENABLEXXX1_VBUS);
+               return;
+       }
+
+       if (irqstat1 & AM335X_VAL_USBXIRQENABLEXXX1_GENERIC) {
+               USB_DBG("Unhandled GENERIC IRQ");
+               CLEAR_IRQ1(AM335X_VAL_USBXIRQENABLEXXX1_GENERIC);
+               return;
+       }
+
+       /* When controller is correctly configured this should never happen: */
+       USB_MSG("Illegal value of IRQxSTAT: 0=%X 1=%X",
+               (unsigned int)irqstat0, (unsigned int)irqstat1);
+       USB_ASSERT(0, "IRQxSTAT error");
+}
+
+
+/*===========================================================================*
+ *    musb_am335x_usb_reset                                                  *
+ *===========================================================================*/
+static void
+musb_am335x_usb_reset(int usb_num)
+{
+       void * r;
+       hcd_reg4 ctrl;
+
+       DEBUG_DUMP;
+
+       r = am335x.ctrl[usb_num].usb.regs;
+
+       /* Set SOFT_RESET bit and wait until it is off */
+       ctrl = HCD_RD4(r, AM335X_REG_USBXCTRL);
+       HCD_SET(ctrl, AM335X_VAL_USBXCTRL_SOFT_RESET);
+       HCD_WR4(r, AM335X_REG_USBXCTRL, ctrl);
+       while (HCD_RD4(r, AM335X_REG_USBXCTRL) &
+               AM335X_VAL_USBXCTRL_SOFT_RESET);
+}
+
+
+/*===========================================================================*
+ *    musb_am335x_otg_enable                                                 *
+ *===========================================================================*/
+static void
+musb_am335x_otg_enable(int usb_num)
+{
+       void * r;
+       hcd_reg4 intreg;
+       hcd_reg4 mode;
+
+       DEBUG_DUMP;
+
+       r = am335x.ctrl[usb_num].usb.regs;
+
+       /* Force host operation */
+       mode = HCD_RD4(r, AM335X_REG_USBXMODE);
+       HCD_SET(mode, AM335X_VAL_USBXMODE_IDDIG_MUX);
+       HCD_CLR(mode, AM335X_VAL_USBXMODE_IDDIG);
+       HCD_WR4(r, AM335X_REG_USBXMODE, mode);
+
+       /* Set all important interrupts to be handled */
+       intreg = HCD_RD4(r, AM335X_REG_USBXIRQENABLESET1);
+       HCD_SET(intreg, AM335X_VAL_USBXIRQENABLEXXX1_SUSPEND            |
+                       AM335X_VAL_USBXIRQENABLEXXX1_RESUME             |
+                       AM335X_VAL_USBXIRQENABLEXXX1_RESET_BABBLE       |
+                       /* AM335X_VAL_USBXIRQENABLEXXX1_SOF             | */
+                       AM335X_VAL_USBXIRQENABLEXXX1_CONNECTED          |
+                       AM335X_VAL_USBXIRQENABLEXXX1_DISCONNECTED       |
+                       AM335X_VAL_USBXIRQENABLEXXX1_SRP                |
+                       AM335X_VAL_USBXIRQENABLEXXX1_VBUS               |
+                       AM335X_VAL_USBXIRQENABLEXXX1_DRVVBUS            |
+                       AM335X_VAL_USBXIRQENABLEXXX1_GENERIC);
+
+       HCD_WR4(r, AM335X_REG_USBXIRQENABLESET1, intreg);
+
+       /* Set endpoint 0 interrupt to be enabled */
+       intreg = HCD_RD4(r, AM335X_REG_USBXIRQENABLESET0);
+       HCD_SET(intreg, AM335X_VAL_USBXIRQENABLEXXX0_EP0);
+       HCD_WR4(r, AM335X_REG_USBXIRQENABLESET0, intreg);
+}
diff --git a/drivers/usbd/hcd/musb/musb_core.c b/drivers/usbd/hcd/musb/musb_core.c
new file mode 100755 (executable)
index 0000000..cf2435a
--- /dev/null
@@ -0,0 +1,570 @@
+/*
+ * Implementation of low level MUSB core logic (variant independent)
+ */
+
+#include <string.h>                            /* memcpy */
+#include <time.h>                              /* nanosleep */
+
+#include <usb/hcd_common.h>
+#include <usb/hcd_interface.h>
+#include <usb/usb_common.h>
+
+#include "musb_core.h"
+#include "musb_regs.h"
+
+
+/*===========================================================================*
+ *    Local defines                                                          *
+ *===========================================================================*/
+#define HCD_COPYBUF_BYTES 64 /* Stack allocated, must be multiple of 4 */
+#define HCD_COPYBUF_WORDS (HCD_COPYBUF_BYTES/4)
+
+
+/*===========================================================================*
+ *    Local prototypes                                                       *
+ *===========================================================================*/
+static void musb_set_state(musb_core_config *);
+static int musb_check_rxpktrdy(void *);
+static void musb_in_stage_cleanup(void *);
+static void musb_clear_rxpktrdy(void *);
+static void musb_clear_statuspkt(void *);
+static int musb_get_count(void *);
+static void musb_read_fifo(void *, hcd_reg1 *, int, int);
+
+
+/*===========================================================================*
+ *                                                                           *
+ *    MUSB core implementation                                               *
+ *                                                                           *
+ *===========================================================================*/
+
+/*===========================================================================*
+ *    musb_set_state                                                         *
+ *===========================================================================*/
+static void
+musb_set_state(musb_core_config * cfg)
+{
+       void * r;
+       hcd_reg1 idx;
+
+       DEBUG_DUMP;
+
+       r = cfg->regs;
+
+       /* Set EP and address to be used in next MUSB command */
+
+       /* Set EP by selecting INDEX */
+       idx = HCD_RD1(r, MUSB_REG_INDEX);
+       HCD_CLR(idx, 0x0F);
+       HCD_SET(idx, cfg->ep & 0x0F);
+       HCD_WR1(r, MUSB_REG_INDEX, idx);
+
+       /* Use device with address 'cfg->addr' */
+       HCD_WR2(r, MUSB_REG_RXFUNCADDR, cfg->addr);
+       HCD_WR2(r, MUSB_REG_TXFUNCADDR, cfg->addr);
+}
+
+
+/*===========================================================================*
+ *    musb_check_rxpktrdy                                                    *
+ *===========================================================================*/
+static int
+musb_check_rxpktrdy(void * cfg)
+{
+       void * r;
+       hcd_reg2 host_csr0;
+
+       DEBUG_DUMP;
+
+       r = ((musb_core_config *)cfg)->regs;
+
+       /* Set EP and device address to be used in this command */
+       musb_set_state((musb_core_config *)cfg);
+
+       /* Get control status register for EP 0 */
+       host_csr0 = HCD_RD2(r, MUSB_REG_HOST_CSR0);
+
+       /* Check for RXPKTRDY */
+       if (host_csr0 & MUSB_VAL_HOST_CSR0_RXPKTRDY)
+               return EXIT_SUCCESS;
+
+       return EXIT_FAILURE;
+}
+
+
+/*===========================================================================*
+ *    musb_in_stage_cleanup                                                  *
+ *===========================================================================*/
+static void
+musb_in_stage_cleanup(void * cfg)
+{
+       DEBUG_DUMP;
+
+       musb_clear_rxpktrdy(cfg);
+       musb_clear_statuspkt(cfg);
+}
+
+
+/*===========================================================================*
+ *    musb_clear_rxpktrdy                                                    *
+ *===========================================================================*/
+static void
+musb_clear_rxpktrdy(void * cfg)
+{
+       void * r;
+       hcd_reg2 host_csr0;
+
+       DEBUG_DUMP;
+
+       r = ((musb_core_config *)cfg)->regs;
+
+       /* Set EP and device address to be used in this command */
+       musb_set_state((musb_core_config *)cfg);
+
+       /* Get control status register for EP 0 */
+       host_csr0 = HCD_RD2(r, MUSB_REG_HOST_CSR0);
+
+       /* Clear RXPKTRDY to signal receive completion */
+       HCD_CLR(host_csr0, MUSB_VAL_HOST_CSR0_RXPKTRDY);
+       HCD_WR2(r, MUSB_REG_HOST_CSR0, host_csr0);
+}
+
+
+/*===========================================================================*
+ *    musb_clear_statuspkt                                                   *
+ *===========================================================================*/
+static void
+musb_clear_statuspkt(void * cfg)
+{
+       void * r;
+       hcd_reg2 host_csr0;
+
+       DEBUG_DUMP;
+
+       r = ((musb_core_config *)cfg)->regs;
+
+       /* Set EP and device address to be used in this command */
+       musb_set_state((musb_core_config *)cfg);
+
+       /* Get control status register for EP 0 */
+       host_csr0 = HCD_RD2(r, MUSB_REG_HOST_CSR0);
+
+       /* Clear STATUSPKT to signal status packet completion */
+       HCD_CLR(host_csr0, MUSB_VAL_HOST_CSR0_STATUSPKT);
+       HCD_WR2(r, MUSB_REG_HOST_CSR0, host_csr0);
+}
+
+
+/*===========================================================================*
+ *    musb_get_count                                                         *
+ *===========================================================================*/
+static int
+musb_get_count(void * cfg)
+{
+       void * r;
+
+       DEBUG_DUMP;
+
+       r = ((musb_core_config *)cfg)->regs;
+
+       /* Set EP and device address to be used in this command */
+       musb_set_state((musb_core_config *)cfg);
+
+       /* Reserved part returns zero so no need to generalize
+        * this return for MUSB_REG_RXCOUNT */
+       return (int)(HCD_RD2(r, MUSB_REG_COUNT0));
+}
+
+
+/*===========================================================================*
+ *    musb_read_fifo                                                         *
+ *===========================================================================*/
+static void
+musb_read_fifo(void * cfg, hcd_reg1 * output, int size, int fifo_num)
+{
+       void * r;
+       hcd_reg4 * word;
+       hcd_reg4 copy_buf[HCD_COPYBUF_WORDS];
+       hcd_addr fifo_addr;
+       int limit;
+       int idx;
+
+       DEBUG_DUMP;
+
+       USB_ASSERT((fifo_num >= 0) && (fifo_num <= 4), "Wrong FIFO number");
+
+       r = ((musb_core_config *)cfg)->regs;
+       fifo_addr = MUSB_REG_FIFO0 + (fifo_num * MUSB_REG_FIFO_LEN);
+
+       /* Set EP and device address to be used in this command */
+       musb_set_state((musb_core_config *)cfg);
+
+       /* Read full words from MUSB FIFO */
+       while (size > 0) {
+               /* Largest amount of bytes that can be copied at a time */
+               limit = (size < HCD_COPYBUF_BYTES) ? size : HCD_COPYBUF_BYTES;
+
+               /* Start copying into that */
+               word = copy_buf;
+
+               /* Read words from FIFO into copy_buf */
+               for (idx = 0; idx < limit; idx += sizeof(*word))
+                       *word++ = HCD_RD4(r, fifo_addr);
+
+               /* Copy and shift */
+               memcpy(output, copy_buf, limit);
+               output += limit;
+               size -= limit;
+       }
+}
+
+
+/*===========================================================================*
+ *    musb_core_start                                                        *
+ *===========================================================================*/
+void
+musb_core_start(void * cfg)
+{
+       void * r;
+       hcd_reg1 devctl;
+
+       DEBUG_DUMP;
+
+       r = ((musb_core_config *)cfg)->regs;
+
+       /* Enable all interrupts valid for host */
+       HCD_WR1(r, MUSB_REG_INTRUSBE,
+               MUSB_VAL_INTRUSBE_SUSPEND                       |
+               MUSB_VAL_INTRUSBE_RESUME                        |
+               MUSB_VAL_INTRUSBE_RESET_BABBLE                  |
+               /* MUSB_VAL_INTRUSBE_SOF                        | */
+               MUSB_VAL_INTRUSBE_CONN                          |
+               MUSB_VAL_INTRUSBE_DISCON                        |
+               MUSB_VAL_INTRUSBE_SESSREQ                       |
+               MUSB_VAL_INTRUSBE_VBUSERR);
+
+       /* Start session */
+       devctl = HCD_RD1(r, MUSB_REG_DEVCTL);
+       HCD_SET(devctl, MUSB_VAL_DEVCTL_SESSION);
+       HCD_WR1(r, MUSB_REG_DEVCTL, devctl);
+}
+
+
+/*===========================================================================*
+ *    musb_core_stop                                                         *
+ *===========================================================================*/
+void
+musb_core_stop(void * cfg)
+{
+       void * r;
+       hcd_reg1 devctl;
+
+       DEBUG_DUMP;
+
+       r = ((musb_core_config *)cfg)->regs;
+
+       /* TODO: add hardware interrupt disable */
+
+       /* Stop session */
+       devctl = HCD_RD1(r, MUSB_REG_DEVCTL);
+       HCD_CLR(devctl, MUSB_VAL_DEVCTL_SESSION);
+       HCD_WR1(r, MUSB_REG_DEVCTL, devctl);
+}
+
+
+/*===========================================================================*
+ *    musb_ep0_config                                                        *
+ *===========================================================================*/
+void
+musb_ep0_config(void * cfg)
+{
+       void * r;
+       hcd_reg1 host_type0;
+       hcd_reg2 intrtxe;
+
+       DEBUG_DUMP;
+
+       r = ((musb_core_config *)cfg)->regs;
+
+       /* Set parameters temporarily */
+       musb_setup_device((musb_core_config *)cfg,
+                       HCD_DEFAULT_EP,
+                       HCD_DEFAULT_ADDR);
+
+       /* Set EP and device address to be used in this command */
+       musb_set_state((musb_core_config *)cfg);
+
+       /* Set high speed for EP0 */
+       host_type0 = HCD_RD1(r, MUSB_REG_HOST_TYPE0);
+       HCD_CLR(host_type0, MUSB_VAL_HOST_TYPE0_MASK);
+       HCD_SET(host_type0, MUSB_VAL_HOST_TYPE0_HIGH_SPEED);
+       HCD_WR1(r, MUSB_REG_HOST_TYPE0, host_type0);
+
+       /* Enable EP interrupt */
+       intrtxe = HCD_RD2(r, MUSB_REG_INTRTXE);
+       HCD_SET(intrtxe, MUSB_VAL_INTRTXE_EP0);
+       HCD_WR2(r, MUSB_REG_INTRTXE, intrtxe);
+}
+
+
+/*===========================================================================*
+ *                                                                           *
+ *    HCD interface implementation                                           *
+ *                                                                           *
+ *===========================================================================*/
+
+/*===========================================================================*
+ *    musb_setup_device                                                      *
+ *===========================================================================*/
+void
+musb_setup_device(void * cfg, hcd_reg1 ep, hcd_reg1 addr)
+{
+       DEBUG_DUMP;
+
+       /* Assign  */
+       ((musb_core_config *)cfg)->ep = ep;
+       ((musb_core_config *)cfg)->addr = addr;
+}
+
+
+/*===========================================================================*
+ *    musb_reset_device                                                      *
+ *===========================================================================*/
+void
+musb_reset_device(void * cfg)
+{
+       void * r;
+       hcd_reg1 power;
+
+       DEBUG_DUMP;
+
+       r = ((musb_core_config *)cfg)->regs;
+
+       /* Write reset bit and high speed negotiation wait for at least
+        * 20ms for reset, clear reset bit and wait for device */
+       power = HCD_RD1(r, MUSB_REG_POWER);
+       HCD_SET(power, MUSB_VAL_POWER_RESET | MUSB_VAL_POWER_HSEN);
+       HCD_WR1(r, MUSB_REG_POWER, power);
+
+       {
+               /* Sleep 25ms */
+               struct timespec nanotm = {0, HCD_NANOSLEEP_MSEC(25)};
+               nanosleep(&nanotm, NULL);
+       }
+
+       power = HCD_RD1(r, MUSB_REG_POWER);
+       HCD_CLR(power, MUSB_VAL_POWER_RESET);
+       HCD_WR1(r, MUSB_REG_POWER, power);
+
+       {
+               /* Sleep 25ms */
+               struct timespec nanotm = {0, HCD_NANOSLEEP_MSEC(25)};
+               nanosleep(&nanotm, NULL);
+       }
+}
+
+
+/*===========================================================================*
+ *    musb_setup_stage                                                       *
+ *===========================================================================*/
+void
+musb_setup_stage(void * cfg, hcd_ctrlrequest * setup)
+{
+       void * r;
+       char * setup_byte;
+       hcd_reg2 host_csr0;
+
+       DEBUG_DUMP;
+
+       r = ((musb_core_config *)cfg)->regs;
+       setup_byte = (char*)setup;
+
+       /* Set EP and device address to be used in this command */
+       musb_set_state((musb_core_config *)cfg);
+
+       /* TODO: check for ongoing transmission */
+
+       /* Put USB setup data into corresponding FIFO */
+       HCD_WR4(r, MUSB_REG_FIFO0, HCD_8TO32(&setup_byte[0]));
+       HCD_WR4(r, MUSB_REG_FIFO0, HCD_8TO32(&setup_byte[sizeof(hcd_reg4)]));
+
+       /* Get control status register for EP 0 */
+       host_csr0 = HCD_RD2(r, MUSB_REG_HOST_CSR0);
+
+       /* Send actual packet from FIFO */
+       HCD_SET(host_csr0, MUSB_VAL_HOST_CSR0_TXPKTRDY |
+                       MUSB_VAL_HOST_CSR0_SETUPPKT);
+
+       HCD_WR2(r, MUSB_REG_HOST_CSR0, host_csr0);
+}
+
+
+/*===========================================================================*
+ *    musb_in_data_stage                                                     *
+ *===========================================================================*/
+void
+musb_in_data_stage(void * cfg)
+{
+       void * r;
+       hcd_reg2 host_csr0;
+
+       DEBUG_DUMP;
+
+       r = ((musb_core_config *)cfg)->regs;
+
+       /* Set EP and device address to be used in this command */
+       musb_set_state((musb_core_config *)cfg);
+
+       /* Get control status register for EP 0 */
+       host_csr0 = HCD_RD2(r, MUSB_REG_HOST_CSR0);
+
+       /* Request IN DATA stage */
+       HCD_SET(host_csr0, MUSB_VAL_HOST_CSR0_REQPKT);
+       HCD_WR2(r, MUSB_REG_HOST_CSR0, host_csr0);
+}
+
+
+/*===========================================================================*
+ *    musb_out_data_stage                                                    *
+ *===========================================================================*/
+void
+musb_out_data_stage(void * cfg)
+{
+       DEBUG_DUMP;
+
+       /* Set EP and device address to be used in this command */
+       musb_set_state((musb_core_config *)cfg);
+
+       /* TODO: not needed for enumeration but will be needed later */
+       ((void)cfg);
+       USB_MSG("NOT IMPLEMENTED");
+}
+
+
+/*===========================================================================*
+ *    musb_in_status_stage                                                   *
+ *===========================================================================*/
+void
+musb_in_status_stage(void * cfg)
+{
+       void * r;
+       hcd_reg2 host_csr0;
+
+       DEBUG_DUMP;
+
+       r = ((musb_core_config *)cfg)->regs;
+
+       /* Set EP and device address to be used in this command */
+       musb_set_state((musb_core_config *)cfg);
+
+       /* Get control status register for EP 0 */
+       host_csr0 = HCD_RD2(r, MUSB_REG_HOST_CSR0);
+
+       /* Request IN STATUS stage */
+       HCD_SET(host_csr0, MUSB_VAL_HOST_CSR0_REQPKT |
+               MUSB_VAL_HOST_CSR0_STATUSPKT);
+
+       HCD_WR2(r, MUSB_REG_HOST_CSR0, host_csr0);
+}
+
+
+/*===========================================================================*
+ *    musb_out_status_stage                                                  *
+ *===========================================================================*/
+void
+musb_out_status_stage(void * cfg)
+{
+       void * r;
+       hcd_reg2 host_csr0;
+
+       DEBUG_DUMP;
+
+       r = ((musb_core_config *)cfg)->regs;
+
+       /* Set EP and device address to be used in this command */
+       musb_set_state((musb_core_config *)cfg);
+
+       /* Get control status register for EP 0 */
+       host_csr0 = HCD_RD2(r, MUSB_REG_HOST_CSR0);
+
+       /* Request OUT STATUS stage */
+       HCD_SET(host_csr0, MUSB_VAL_HOST_CSR0_TXPKTRDY |
+               MUSB_VAL_HOST_CSR0_STATUSPKT);
+
+       HCD_WR2(r, MUSB_REG_HOST_CSR0, host_csr0);
+}
+
+
+/*===========================================================================*
+ *    musb_read_data                                                         *
+ *===========================================================================*/
+int
+musb_read_data(void * cfg, hcd_reg1 * buffer, int buffer_num)
+{
+       int count0;
+
+       DEBUG_DUMP;
+
+       /* Check if anything received at all */
+       if (EXIT_SUCCESS != musb_check_rxpktrdy(cfg)) {
+               USB_MSG("RXPKTRDY not set when receiving");
+               return HCD_READ_ERR;
+       }
+
+       /* Number of bytes received at EP0 */
+       count0 = musb_get_count(cfg);
+
+       /* Read from given FIFO */
+       if ((NULL != buffer) && (count0 > 0))
+               musb_read_fifo(cfg, buffer, count0, buffer_num);
+
+       /* Cleanup after reading */
+       musb_in_stage_cleanup(cfg);
+
+       return count0;
+}
+
+
+/*===========================================================================*
+ *    musb_check_error                                                       *
+ *===========================================================================*/
+int
+musb_check_error(void * cfg)
+{
+       void * r;
+       hcd_reg2 host_csr0;
+
+       DEBUG_DUMP;
+
+       r = ((musb_core_config *)cfg)->regs;
+
+       /* Set EP and device address to be used in this command */
+       musb_set_state((musb_core_config *)cfg);
+
+       /* Get control status register for EP 0 */
+       host_csr0 = HCD_RD2(r, MUSB_REG_HOST_CSR0);
+
+       /* Check for common errors */
+       if (host_csr0 & MUSB_VAL_HOST_CSR0_ERROR) {
+               USB_MSG("HOST_CSR0 ERROR: %04X", host_csr0);
+               HCD_CLR(host_csr0, MUSB_VAL_HOST_CSR0_ERROR);
+               HCD_WR2(r, MUSB_REG_HOST_CSR0, host_csr0);
+               return EXIT_FAILURE;
+       }
+
+       if (host_csr0 & MUSB_VAL_HOST_CSR0_RXSTALL) {
+               USB_MSG("HOST_CSR0 STALL: %04X", host_csr0);
+               HCD_CLR(host_csr0, MUSB_VAL_HOST_CSR0_RXSTALL);
+               HCD_WR2(r, MUSB_REG_HOST_CSR0, host_csr0);
+               return EXIT_FAILURE;
+       }
+
+       if (host_csr0 & MUSB_VAL_HOST_CSR0_NAK_TIMEOUT) {
+               USB_MSG("HOST_CSR0 NAK_TIMEOUT: %04X", host_csr0);
+               HCD_CLR(host_csr0, MUSB_VAL_HOST_CSR0_NAK_TIMEOUT);
+               HCD_WR2(r, MUSB_REG_HOST_CSR0, host_csr0);
+               return EXIT_FAILURE;
+       }
+
+       return EXIT_SUCCESS;
+}
diff --git a/drivers/usbd/hcd/musb/musb_core.h b/drivers/usbd/hcd/musb/musb_core.h
new file mode 100755 (executable)
index 0000000..c85aa18
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Interface of low level MUSB core logic (variant independent)
+ */
+
+#ifndef _MUSB_CORE_H_
+#define _MUSB_CORE_H_
+
+#include <usb/hcd_common.h>
+
+
+/*===========================================================================*
+ *    Types and constants                                                    *
+ *===========================================================================*/
+/* Structure to hold Mentor USB core configuration
+ * May be more than one on a single chip
+ * Should be initialized by MUSB's variant specific code (like AM335x) */
+typedef struct {
+
+       void * regs;    /* Points to beginning of memory mapped registers */
+       hcd_reg1 ep;    /* Currently used endpoint */
+       hcd_reg1 addr;  /* Currently used address */
+}
+musb_core_config;
+
+
+/*===========================================================================*
+ *    Function prototypes                                                    *
+ *===========================================================================*/
+/* Only to be used outside generic HCD code */
+void musb_core_start(void *);
+void musb_core_stop(void *);
+void musb_ep0_config(void *);
+
+
+/* For HCD interface */
+void musb_setup_device(void *, hcd_reg1, hcd_reg1);
+void musb_reset_device(void *);
+void musb_setup_stage(void *, hcd_ctrlrequest *);
+void musb_in_data_stage(void *);
+void musb_out_data_stage(void *);
+void musb_in_status_stage(void *);
+void musb_out_status_stage(void *);
+int musb_read_data(void *, hcd_reg1 *, int);
+int musb_check_error(void *);
+
+
+#endif /* !_MUSB_CORE_H_ */
diff --git a/drivers/usbd/hcd/musb/musb_regs.h b/drivers/usbd/hcd/musb/musb_regs.h
new file mode 100755 (executable)
index 0000000..15fd554
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Common MUSB core registers definitions
+ */
+
+#ifndef _MUSB_REGS_H_
+#define _MUSB_REGS_H_
+
+#include <usb/hcd_common.h>
+
+
+/*===========================================================================*
+ *    MUSB core register offsets                                             *
+ *===========================================================================*/
+#define MUSB_REG_FADDR                         0x00u
+#define MUSB_REG_POWER                         0x01u
+#define MUSB_REG_INTRTX                                0x02u
+#define MUSB_REG_INTRRX                                0x04u
+#define MUSB_REG_INTRTXE                       0x06u
+#define MUSB_REG_INTRRXE                       0x08u
+#define MUSB_REG_INTRUSB                       0x0Au
+#define MUSB_REG_INTRUSBE                      0x0Bu
+#define MUSB_REG_FRAME                         0x0Cu
+#define MUSB_REG_INDEX                         0x0Eu
+#define MUSB_REG_TESTMODE                      0x0Fu
+
+/* Proxy registers for endpoint configuration,
+ * that correspond to specific endpoint's register space
+ * selected with MUSB_REG_INDEX */
+#define MUSB_REG_TXMAXP                                0x10u
+#define MUSB_REG_PERI_CSR0                     0x12u
+#define MUSB_REG_HOST_CSR0                             MUSB_REG_PERI_CSR0
+#define MUSB_REG_PERI_TXCSR                            MUSB_REG_PERI_CSR0
+#define MUSB_REG_HOST_TXCSR                            MUSB_REG_PERI_CSR0
+#define MUSB_REG_RXMAXP                                0x14u
+#define MUSB_REG_PERI_RXCSR                    0x16u
+#define MUSB_REG_HOST_RXCSR                            MUSB_PERI_RXCSR
+#define MUSB_REG_COUNT0                                0x18u
+#define MUSB_REG_RXCOUNT                               MUSB_COUNT0
+#define MUSB_REG_HOST_TYPE0                    0x1Au
+#define MUSB_REG_HOST_TXTYPE                           MUSB_HOST_TYPE0
+#define MUSB_REG_HOST_NAKLIMIT0                        0x1Bu
+#define MUSB_REG_HOST_TXINTERVAL                       MUSB_HOST_NAKLIMIT0
+#define MUSB_REG_HOST_RXTYPE                   0x1Cu
+#define MUSB_REG_HOST_RXINTERVAL               0x1Du
+#define MUSB_REG_CONFIGDATA                    0x1Fu
+
+#define MUSB_REG_FIFO0                         0x20u
+#define MUSB_REG_FIFO1                         0x24u
+#define MUSB_REG_FIFO2                         0x28u
+#define MUSB_REG_FIFO3                         0x2Cu
+#define MUSB_REG_FIFO4                         0x30u
+#define MUSB_REG_FIFO_LEN                      0x04u
+
+#define MUSB_REG_DEVCTL                                0x60u
+#define MUSB_REG_TXFIFOSZ                      0x62u
+#define MUSB_REG_RXFIFOSZ                      0x63u
+#define MUSB_REG_TXFIFOADDR                    0x64u
+#define MUSB_REG_RXFIFOADDR                    0x66u
+
+#define MUSB_REG_TXFUNCADDR                    0x80u
+#define MUSB_REG_TXHUBADDR                     0x82u
+#define MUSB_REG_TXHUBPORT                     0x83u
+#define MUSB_REG_RXFUNCADDR                    0x84u
+#define MUSB_REG_RXHUBADDR                     0x86u
+#define MUSB_REG_RXHUBPORT                     0x87u
+
+
+/*===========================================================================*
+ *    MUSB core register values                                              *
+ *===========================================================================*/
+/* POWER */
+#define MUSB_VAL_POWER_ENSUSPM                 HCD_BIT(0)
+#define MUSB_VAL_POWER_SUSPENDM                        HCD_BIT(1)
+#define MUSB_VAL_POWER_RESUME                  HCD_BIT(2)
+#define MUSB_VAL_POWER_RESET                   HCD_BIT(3)
+#define MUSB_VAL_POWER_HSMODE                  HCD_BIT(4)
+#define MUSB_VAL_POWER_HSEN                    HCD_BIT(5)
+#define MUSB_VAL_POWER_SOFTCONN                        HCD_BIT(6)
+#define MUSB_VAL_POWER_ISOUPDATE               HCD_BIT(7)
+
+/* DEVCTL */
+#define MUSB_VAL_DEVCTL_SESSION                        HCD_BIT(0)
+#define MUSB_VAL_DEVCTL_HOSTREQ                        HCD_BIT(1)
+#define MUSB_VAL_DEVCTL_HOSTMODE               HCD_BIT(2)
+#define MUSB_VAL_DEVCTL_VBUS_1                 HCD_BIT(3)
+#define MUSB_VAL_DEVCTL_VBUS_2                 HCD_BIT(4)
+#define MUSB_VAL_DEVCTL_VBUS_3                 (HCD_BIT(3) | HCD_BIT(4))
+#define MUSB_VAL_DEVCTL_LSDEV                  HCD_BIT(5)
+#define MUSB_VAL_DEVCTL_FSDEV                  HCD_BIT(6)
+#define MUSB_VAL_DEVCTL_BDEVICE                        HCD_BIT(7)
+
+/* INTRUSBE */
+#define MUSB_VAL_INTRUSBE_SUSPEND              HCD_BIT(0)
+#define MUSB_VAL_INTRUSBE_RESUME               HCD_BIT(1)
+#define MUSB_VAL_INTRUSBE_RESET_BABBLE         HCD_BIT(2)
+#define MUSB_VAL_INTRUSBE_SOF                  HCD_BIT(3)
+#define MUSB_VAL_INTRUSBE_CONN                 HCD_BIT(4)
+#define MUSB_VAL_INTRUSBE_DISCON               HCD_BIT(5)
+#define MUSB_VAL_INTRUSBE_SESSREQ              HCD_BIT(6)
+#define MUSB_VAL_INTRUSBE_VBUSERR              HCD_BIT(7)
+
+/* HOST_TYPE0 */
+#define MUSB_VAL_HOST_TYPE0_MASK               (HCD_BIT(6) | HCD_BIT(7))
+#define MUSB_VAL_HOST_TYPE0_HIGH_SPEED         HCD_BIT(6)
+#define MUSB_VAL_HOST_TYPE0_FULL_SPEED         HCD_BIT(7)
+#define MUSB_VAL_HOST_TYPE0_LOW_SPEED          (HCD_BIT(6) | HCD_BIT(7))
+
+/* INTRTXE */
+#define MUSB_VAL_INTRTXE_EP0                   HCD_BIT(0)
+#define MUSB_VAL_INTRTXE_EP1TX                 HCD_BIT(1)
+#define MUSB_VAL_INTRTXE_EP2TX                 HCD_BIT(2)
+#define MUSB_VAL_INTRTXE_EP3TX                 HCD_BIT(3)
+#define MUSB_VAL_INTRTXE_EP4TX                 HCD_BIT(4)
+
+/* HOST_CSR0 */
+#define MUSB_VAL_HOST_CSR0_RXPKTRDY            HCD_BIT(0)
+#define MUSB_VAL_HOST_CSR0_TXPKTRDY            HCD_BIT(1)
+#define MUSB_VAL_HOST_CSR0_RXSTALL             HCD_BIT(2)
+#define MUSB_VAL_HOST_CSR0_SETUPPKT            HCD_BIT(3)
+#define MUSB_VAL_HOST_CSR0_ERROR               HCD_BIT(4)
+#define MUSB_VAL_HOST_CSR0_REQPKT              HCD_BIT(5)
+#define MUSB_VAL_HOST_CSR0_STATUSPKT           HCD_BIT(6)
+#define MUSB_VAL_HOST_CSR0_NAK_TIMEOUT         HCD_BIT(7)
+#define MUSB_VAL_HOST_CSR0_FLUSHFIFO           HCD_BIT(8)
+
+#endif /* !_MUSB_REGS_H_ */
diff --git a/drivers/usbd/include/usb/hcd_common.h b/drivers/usbd/include/usb/hcd_common.h
new file mode 100755 (executable)
index 0000000..0bb0299
--- /dev/null
@@ -0,0 +1,214 @@
+/*
+ * Contains commonly used types and procedures, for HCD handling/initialization
+ * If possible, everything OS specific (IPC, virtual memory...) should be here
+ */
+
+#ifndef _HCD_COMMON_H_
+#define _HCD_COMMON_H_
+
+#include <ddekit/thread.h>
+#include <ddekit/semaphore.h>
+#include <ddekit/usb.h>
+
+#include <minix/usb.h>                         /* for setup structures */
+#include <minix/usb_ch9.h>                     /* for descriptor structures */
+
+
+/*===========================================================================*
+ *    USB register handling defines                                          *
+ *===========================================================================*/
+/* Helper type used for register bitwise access */
+#define HCD_BIT(num)                           (0x01u << (num))
+
+/* Unsigned type that can hold all possible addresses */
+typedef unsigned long                          hcd_addr;
+
+/* Register types */
+typedef unsigned long                          hcd_reg4;
+typedef unsigned short                         hcd_reg2;
+typedef unsigned char                          hcd_reg1;
+
+/* For register dereferencing */
+#define _HCD_REG4                              hcd_reg4 * volatile
+#define _HCD_REG2                              hcd_reg2 * volatile
+#define _HCD_REG1                              hcd_reg1 * volatile
+
+/* Scalar address to dereference */
+#define _HCD_ADDR(base, off)                   (((hcd_addr)(base))+(off))
+
+/* Defines for fixed size register access
+ * May cause unaligned memory access */
+#define HCD_WR4(base, off, val)        (*((_HCD_REG4)_HCD_ADDR(base, off)) = (val))
+#define HCD_WR2(base, off, val)        (*((_HCD_REG2)_HCD_ADDR(base, off)) = (val))
+#define HCD_WR1(base, off, val)        (*((_HCD_REG1)_HCD_ADDR(base, off)) = (val))
+#define HCD_RD4(base, off)     (*((_HCD_REG4)_HCD_ADDR(base, off)))
+#define HCD_RD2(base, off)     (*((_HCD_REG2)_HCD_ADDR(base, off)))
+#define HCD_RD1(base, off)     (*((_HCD_REG1)_HCD_ADDR(base, off)))
+
+/* Other useful defines */
+#define HCD_SET(val, bits)     ((val)|=(bits))
+#define HCD_CLR(val, bits)     ((val)&=~(bits))
+
+/* Alignment safe conversion from 'bytes' array to a word */
+#define HCD_8TO32(bytes)       (((bytes)[0])           |               \
+                               (((bytes)[1])<<8)       |               \
+                               (((bytes)[2])<<16)      |               \
+                               (((bytes)[3])<<24))
+
+/* Convert type's 'sizeof' to 4-byte words count */
+#define HCD_SIZEOF_TO_4(type)  ((sizeof(type)+3)/4)
+
+
+/*===========================================================================*
+ *    USB descriptor types                                                   *
+ *===========================================================================*/
+typedef struct usb_ctrlrequest                 hcd_ctrlrequest;
+typedef usb_descriptor_t                       hcd_descriptor;
+typedef usb_device_descriptor_t                        hcd_device_descriptor;
+typedef usb_config_descriptor_t                        hcd_config_descriptor;
+typedef usb_interface_descriptor_t             hcd_interface_descriptor;
+typedef usb_endpoint_descriptor_t              hcd_endpoint_descriptor;
+typedef usb_string_descriptor_t                        hcd_string_descriptor;
+
+
+/*===========================================================================*
+ *    HCD descriptor tree types                                              *
+ *===========================================================================*/
+typedef struct hcd_endpoint {
+
+       hcd_endpoint_descriptor descriptor;
+}
+hcd_endpoint;
+
+typedef struct hcd_interface {
+
+       hcd_interface_descriptor descriptor;
+       hcd_endpoint * endpoint;
+       int num_endpoints;
+}
+hcd_interface;
+
+typedef struct hcd_configuration {
+
+       hcd_config_descriptor descriptor;
+       hcd_interface * interface;
+       int num_interfaces;
+}
+hcd_configuration;
+
+
+/*===========================================================================*
+ *    HCD device helper types                                                *
+ *===========================================================================*/
+typedef                                        void (*hcd_thread_function)(void *);
+typedef ddekit_thread_t                        hcd_thread;
+typedef ddekit_sem_t                   hcd_lock;
+typedef struct hcd_driver_state                hcd_driver_state;
+typedef struct ddekit_usb_urb          hcd_urb;
+
+typedef enum {
+
+       HCD_STATE_DISCONNECTED = 0,             /* default for initialization */
+       HCD_STATE_CONNECTION_PENDING,
+       HCD_STATE_CONNECTED
+}
+hcd_state;
+
+/* Largest value that can be transfered by this driver at a time
+ * see MAXPAYLOAD in TXMAXP/RXMAXP */
+#define MAX_WTOTALLENGTH 1024
+
+typedef struct hcd_device_state {
+
+       hcd_driver_state * driver;
+       hcd_thread * thread;
+       hcd_lock * lock;
+       hcd_urb * urb;
+       void * data;
+
+       hcd_device_descriptor device_desc;
+       hcd_configuration config_tree;
+       hcd_reg1 max_packet_size;
+
+       hcd_state state;
+
+       /* Number of bytes received/transmitted in last transfer */
+       int data_len;
+       /* TODO: forcefully align buffer to make things clear? */
+       /* Buffer for each device to hold transfered data */
+       hcd_reg1 buffer[MAX_WTOTALLENGTH];
+}
+hcd_device_state;
+
+
+/*===========================================================================*
+ *    Other definitions                                                      *
+ *===========================================================================*/
+#define HCD_NANOSLEEP_SEC(sec)         ((sec)  * 1000000000)
+#define HCD_NANOSLEEP_MSEC(msec)       ((msec) * 1000000)
+#define HCD_NANOSLEEP_USEC(usec)       ((usec) * 1000)
+
+/* Default USB communication parameters */
+#define HCD_DEFAULT_EP         0x00
+#define HCD_DEFAULT_ADDR       0x00
+
+/* TODO: one device */
+#define HCD_ATTACHED_ADDR      0x01
+
+
+/*===========================================================================*
+ *    Operating system specific                                              *
+ *===========================================================================*/
+/* Generic method for registering interrupts */
+int hcd_os_interrupt_attach(int irq, void (*init)(void *),
+                               void (*isr)(void *), void *priv);
+
+/* Generic method for unregistering interrupts */
+void hcd_os_interrupt_detach(int);
+
+/* Generic method for enabling interrupts */
+void hcd_os_interrupt_enable(int);
+
+/* Generic method for disabling interrupts */
+void hcd_os_interrupt_disable(int);
+
+/* Returns pointer to memory mapped for given arguments */
+void * hcd_os_regs_init(unsigned long, unsigned long);
+
+/* Unregisters mapped memory */
+int hcd_os_regs_deinit(unsigned long, unsigned long);
+
+/* Configure clocking */
+int hcd_os_clkconf(unsigned long, unsigned long, unsigned long);
+
+/* Release clocking */
+int hcd_os_clkconf_release(void);
+
+
+/*===========================================================================*
+ *    Device handling calls                                                  *
+ *===========================================================================*/
+/* Initializes device threading on connection */
+int hcd_connect_device(hcd_device_state *, hcd_thread_function);
+
+/* Cleans after device disconnection */
+void hcd_disconnect_device(hcd_device_state *);
+
+/* Locks device thread until 'hcd_device_continue' */
+void hcd_device_wait(hcd_device_state *);
+
+/* Unlocks device thread halted by 'hcd_device_wait' */
+void hcd_device_continue(hcd_device_state *);
+
+
+/*===========================================================================*
+ *    Descriptor tree calls                                                  *
+ *===========================================================================*/
+/* Creates descriptor tree based on given buffer */
+int hcd_buffer_to_tree(hcd_reg1 *, int, hcd_configuration *);
+
+/* Frees descriptor tree */
+void hcd_tree_cleanup(hcd_configuration *);
+
+
+#endif /* !_HCD_COMMON_H_ */
diff --git a/drivers/usbd/include/usb/hcd_ddekit.h b/drivers/usbd/include/usb/hcd_ddekit.h
new file mode 100755 (executable)
index 0000000..67cb325
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * Whatever must be known to DDEkit callers
+ */
+
+#ifndef _HCD_DDEKIT_H_
+#define _HCD_DDEKIT_H_
+
+#include <usb/hcd_common.h>
+
+/*===========================================================================*
+ *    External declarations                                                  *
+ *===========================================================================*/
+void hcd_connect_cb(hcd_device_state *);
+void hcd_disconnect_cb(hcd_device_state *);
+void hcd_completion_cb(void *);
+
+
+#endif /* !_HCD_DDEKIT_H_ */
diff --git a/drivers/usbd/include/usb/hcd_interface.h b/drivers/usbd/include/usb/hcd_interface.h
new file mode 100755 (executable)
index 0000000..20ee3ba
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Interface for HCD
+ *
+ * This file holds prototypes that must be implemented by HCD
+ * and event call that should be called when interrupt occurred
+ */
+
+#ifndef _HCD_INTERFACE_H_
+#define _HCD_INTERFACE_H_
+
+#include <usb/hcd_common.h>
+
+
+/*===========================================================================*
+ *    HCD event handling types                                               *
+ *===========================================================================*/
+/* Possible HCD events */
+typedef enum {
+
+       HCD_EVENT_CONNECTED,
+       HCD_EVENT_DISCONNECTED,
+       HCD_EVENT_ENDPOINT
+}
+hcd_event;
+
+/* Possible HCD sub-events */
+typedef enum {
+
+       HCD_SUBEVENT_NONE,
+       HCD_SUBEVENT_EP0,
+}
+hcd_subevent;
+
+
+/*===========================================================================*
+ *    HCD additional defines                                                 *
+ *===========================================================================*/
+#define HCD_READ_ERR -1
+
+
+/*===========================================================================*
+ *    HCD driver structure to be filled
+ *===========================================================================*/
+struct hcd_driver_state {
+       /* Standard USB controller procedures */
+       void            (*setup_device)         (void *, hcd_reg1, hcd_reg1);
+       void            (*reset_device)         (void *);
+       void            (*setup_stage)          (void *, hcd_ctrlrequest *);
+       void            (*in_data_stage)        (void *);
+       void            (*out_data_stage)       (void *);
+       void            (*in_status_stage)      (void *);
+       void            (*out_status_stage)     (void *);
+       int             (*read_data)            (void *, hcd_reg1 *, int);
+       int             (*check_error)          (void *);
+
+       /* Controller's private data (like mapped registers) */
+       void *          private_data;
+
+       /* Current state to be handled by driver */
+       hcd_event       event;
+       hcd_subevent    subevent;
+};
+
+
+/*===========================================================================*
+ *    HCD event handling routine                                             *
+ *===========================================================================*/
+/* Handle asynchronous event
+ * This must be called in case of specific HCD interrupts listed above */
+void hcd_handle_event(hcd_driver_state *);
+
+
+#endif /* !_HCD_INTERFACE_H_ */
diff --git a/drivers/usbd/include/usb/hcd_platforms.h b/drivers/usbd/include/usb/hcd_platforms.h
new file mode 100755 (executable)
index 0000000..38bc3c1
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Externally visible interface for possible USB controllers
+ */
+
+#ifndef _HCD_PLATFORMS_H_
+#define _HCD_PLATFORMS_H_
+
+
+/*===========================================================================*
+ *    MUSB                                                                   *
+ *===========================================================================*/
+/* ----- AM335X ----- */
+int musb_am335x_init(void);
+void musb_am335x_deinit(void);
+/* ----- AM/DM37X ----- */
+int musb_dm37x_init(void);
+void musb_dm37x_deinit(void);
+
+
+#endif /* !_HCD_PLATFORMS_H_ */
diff --git a/drivers/usbd/include/usb/usb_common.h b/drivers/usbd/include/usb/usb_common.h
new file mode 100755 (executable)
index 0000000..f4f82f2
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Whatever is commonly used throughout USB code
+ */
+
+#ifndef _USB_COMMON_H_
+#define _USB_COMMON_H_
+
+/* For commonly used: NULL, EXIT_*, and stuff like that */
+#include <stdlib.h>
+
+/* Current printf implementation for dumping important messages */
+#include <stdio.h>
+
+#if 1
+/* TODO: should be elsewhere */
+#define DEBUG
+#endif
+
+
+/*===========================================================================*
+ *    Standard output message                                                *
+ *===========================================================================*/
+#define USB_MSG(fmt, ...)                                              \
+               do {                                                    \
+                       printf("USBD: ");                               \
+                       printf(fmt, ##__VA_ARGS__);                     \
+                       printf("\n");                                   \
+               } while(0)
+
+
+/*===========================================================================*
+ *    Debug helpers                                                          *
+ *===========================================================================*/
+#ifdef DEBUG
+#define DEBUG_DUMP                                                     \
+               do {                                                    \
+                       printf("USBD (DEBUG %s)\n", __func__);          \
+               } while(0)
+
+#define USB_DBG(fmt, ...)                                              \
+               do {                                                    \
+                       printf("USBD (DEBUG %s): ", __func__);          \
+                       printf(fmt, ##__VA_ARGS__);                     \
+                       printf("\n");                                   \
+               } while(0)
+
+#else
+#define DEBUG_DUMP
+#define USB_DBG(fmt, ...)
+#endif
+
+
+/*===========================================================================*
+ *    Assert for USB code                                                    *
+ *===========================================================================*/
+#define USB_ASSERT(cond, otherwise)                                    \
+               do {                                                    \
+                       if(!(cond)) {                                   \
+                               USB_MSG("ERROR - "otherwise);           \
+                               exit(EXIT_FAILURE);                     \
+                       }                                               \
+               } while(0)
+
+
+#endif /* !_USB_COMMON_H_ */
diff --git a/drivers/usbd/include/usb/usbd_interface.h b/drivers/usbd/include/usb/usbd_interface.h
new file mode 100755 (executable)
index 0000000..fbf192c
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Interface for USBD
+ *
+ * This file holds prototypes that must be implemented by platform
+ * specific USBD
+ *
+ * Must be implemented once per USBD but may be used for multiple
+ * controllers at a time when platform has more than one HCD
+ */
+
+#ifndef _USBD_INTERFACE_H_
+#define _USBD_INTERFACE_H_
+
+/*===========================================================================*
+ *    Prototypes to be implemented                                           *
+ *===========================================================================*/
+/* Must set up HCDs in general and interrupts to
+ * be handled by DDEkit in particular */
+int usbd_init_hcd(void);
+
+/* Should clean whatever usbd_init_hcd used */
+void usbd_deinit_hcd(void);
+
+#endif /* !_USBD_INTERFACE_H_ */
diff --git a/drivers/usbd/usbd.conf b/drivers/usbd/usbd.conf
new file mode 100755 (executable)
index 0000000..0ecb10f
--- /dev/null
@@ -0,0 +1,14 @@
+service usbd
+{
+       system
+                       PRIVCTL 
+                       UMAP
+                       IRQCTL
+                       ;
+       irq
+                       92 #BeagleXM
+                       17 #BeagleBoneWhite
+                       18 #BeagleBoneWhite
+                       19 #BeagleBoneWhite
+                       ;
+};