CONFIG_LOGO_LINUX_CLUT224=y
# CONFIG_SOUND is not set
# CONFIG_HID_SUPPORT is not set
-# CONFIG_USB_SUPPORT is not set
+CONFIG_USB_SUPPORT=y
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEVICEFS is not set
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+CONFIG_USB_OTG=y
+CONFIG_USB_OTG_WHITELIST=y
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+# CONFIG_USB_MON is not set
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
+# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_WHCI_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_YUREX is not set
+# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
+CONFIG_USB_OTG_UTILS=y
+# CONFIG_USB_OTG_WAKELOCK is not set
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_NOP_USB_XCEIV is not set
+# CONFIG_USB_LANGWELL_OTG is not set
+# CONFIG_USB_PENWELL_OTG is not set
+# CONFIG_USB_PENWELL_OTG_TEST is not set
+CONFIG_USB_DWC_OTG_XCEIV=y
# CONFIG_UWB is not set
CONFIG_MMC=y
# CONFIG_MMC_DEBUG is not set
#include <linux/usb/gadget.h>
#include <linux/usb/dwc_otg3.h>
+#define SUPPORT_USER_ID_CHANGE_EVENTS
+static int otg_id = -1;
static struct mutex lock;
static const char driver_name[] = "dwc_otg3";
static void __devexit dwc_otg_remove(struct pci_dev *pdev);
static enum dwc_otg_state do_connector_id_status(struct dwc_otg2 *otg)
{
- u32 events = 0;
+ u32 events = 0, user_events = 0;
enum dwc_otg_state state = DWC_STATE_INVALID;
- u32 osts = 0;
otg_dbg(otg, "\n");
-
/* Reset ADP related registers */
otg_write(otg, ADPCFG, 0);
otg_write(otg, ADPCTL, 0);
msleep(60);
+#ifndef SUPPORT_USER_ID_CHANGE_EVENTS
osts = otg_read(otg, OSTS);
if (!(osts & OSTS_CONN_ID_STS)) {
otg_dbg(otg, "Connector ID is A\n");
else
otg_dbg(otg, "B session invalied, so haven't connect HOST\n");
}
+#endif
sleep_until_event(otg, OEVT_CONN_ID_STS_CHNG_EVNT \
| OEVT_B_DEV_VBUS_CHNG_EVNT \
| OEVT_B_DEV_SES_VLD_DET_EVNT, \
- 0, 0, &events, NULL, NULL, 0);
+ 0, USER_ID_B_CHANGE_EVENT \
+ | USER_ID_A_CHANGE_EVENT, &events,\
+ NULL, &user_events, 0);
if (events & (OEVT_B_DEV_VBUS_CHNG_EVNT | \
OEVT_B_DEV_SES_VLD_DET_EVNT)) {
state = DWC_STATE_A_HOST;
}
+#ifdef SUPPORT_USER_ID_CHANGE_EVENTS
+ if (user_events & USER_ID_A_CHANGE_EVENT) {
+ otg_dbg(otg, "events is user id A change\n");
+ state = DWC_STATE_A_HOST;
+ }
+
+ if (user_events & USER_ID_B_CHANGE_EVENT) {
+ otg_dbg(otg, "events is user id B change\n");
+ state = DWC_STATE_B_PERIPHERAL;
+ }
+#endif
return state;
}
ret = start_host(otg);
otg_mask = OEVT_CONN_ID_STS_CHNG_EVNT;
+ user_mask = USER_ID_B_CHANGE_EVENT;
rc = sleep_until_event(otg,
otg_mask, 0, user_mask,
otg_mask = OEVT_CONN_ID_STS_CHNG_EVNT \
| OEVT_B_DEV_VBUS_CHNG_EVNT \
| OEVT_B_DEV_SES_VLD_DET_EVNT;
- user_mask = 0;
+
+ user_mask = USER_ID_A_CHANGE_EVENT;
rc = sleep_until_event(otg,
otg_mask, 0, user_mask,
if (otg_events & OEVT_B_DEV_VBUS_CHNG_EVNT) {
otg_dbg(otg, "OEVT_B_DEV_VBUS_CHNG_EVNT!\n");
- state = DWC_STATE_CHARGER_DETECTION;
+ return DWC_STATE_CHARGER_DETECTION;
}
if (otg_events & OEVT_B_DEV_SES_VLD_DET_EVNT) {
otg_dbg(otg, "OEVT_B_DEV_SES_VLD_DET_EVNT!\n");
- state = DWC_STATE_CHARGER_DETECTION;
+ return DWC_STATE_CHARGER_DETECTION;
}
return DWC_STATE_INVALID;
set_freezable();
reset_hw(otg);
+#ifndef SUPPORT_USER_ID_CHANGE_EVENTS
if (request_irq(otg->irqnum, dwc_otg_irq, IRQF_SHARED,
driver_name, otg) != 0) {
otg_dbg(otg,
"request interrupt %d failed\n", otg->irqnum);
return -EINVAL;
}
+#endif
otg_dbg(otg, "Thread running\n");
while (otg->state != DWC_STATE_TERMINATED) {
static void start_main_thread(struct dwc_otg2 *otg)
{
mutex_lock(&lock);
- if (!otg->main_thread && otg->otg.gadget && otg->otg.host) {
+ if (!otg->main_thread /* && otg->otg.gadget */&& otg->otg.host) {
otg_dbg(otg, "Starting OTG main thread\n");
otg->main_thread = kthread_create(otg_main_thread, otg, "otg");
wake_up_process(otg->main_thread);
struct dwc_otg2 *otg;
if (!x) {
- otg_err(otg, "%s, otg is NULL!\n", __func__);
+ otg_err(otg, "otg is NULL!\n");
return -ENODEV;
}
struct dwc_otg2 *otg;
if (!x) {
- otg_err(otg, "%s, otg is NULL!\n", __func__);
+ otg_err(otg, "otg is NULL!\n");
return -ENODEV;
}
unsigned long flags;
struct dwc_otg2 *otg;
if (!x) {
- otg_err(otg, "%s otg is NULL!\n", __func__);
+ otg_err(otg, "otg is NULL!\n");
return -ENODEV;
}
return 0;
}
-static struct dwc_otg2 *the_transceiver;
+#ifdef SUPPORT_USER_ID_CHANGE_EVENTS
+static ssize_t store_otg_id(struct device *_dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct dwc_otg2 *otg = the_transceiver;
+ unsigned long flags;
+
+ if (count != 2) {
+ otg_err(otg, "return EINVAL\n");
+ return -EINVAL;
+ }
+
+ if (count > 0 && buf[count-1] == '\n')
+ ((char *) buf)[count-1] = 0;
+
+ switch (buf[0]) {
+ case 'a':
+ case 'A':
+ otg_dbg(otg, "Change ID to A\n");
+ otg->user_events |= USER_ID_A_CHANGE_EVENT;
+ spin_lock_irqsave(&otg->lock, flags);
+ wakeup_main_thread(otg);
+ otg_id = 0;
+ spin_unlock_irqrestore(&otg->lock, flags);
+ return count;
+ case 'b':
+ case 'B':
+ otg_dbg(otg, "Change ID to B\n");
+ otg->user_events |= USER_ID_B_CHANGE_EVENT;
+ spin_lock_irqsave(&otg->lock, flags);
+ wakeup_main_thread(otg);
+ otg_id = 1;
+ spin_unlock_irqrestore(&otg->lock, flags);
+ return count;
+ default:
+ otg_err(otg, "Just support change ID to A!\n");
+ return -EINVAL;
+ }
+
+ return count;
+}
+
+static ssize_t
+show_otg_id(struct device *_dev, struct device_attribute *attr, char *buf)
+{
+ char *next;
+ unsigned size, t;
+
+ next = buf;
+ size = PAGE_SIZE;
+
+ t = scnprintf(next, size,
+ "USB OTG ID: %s\n",
+ (otg_id ? "B" : "A")
+ );
+ size -= t;
+ next += t;
+
+ return PAGE_SIZE - size;
+}
+static DEVICE_ATTR(otg_id, S_IRUGO|S_IWUSR|S_IWGRP,\
+ show_otg_id, store_otg_id);
+#endif
+
static int dwc_otg_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
struct platform_device *dwc_host, *dwc_gadget;
unsigned long resource, len;
int retval;
- otg_dbg(otg, "%s is calling\n", __func__);
if (pci_enable_device(pdev) < 0) {
otg_err(otg, "pci device enable failed\n");
otg->gadget = dwc_gadget;
otg->irqnum = pdev->irq;
+#ifdef SUPPORT_USER_ID_CHANGE_EVENTS
+ retval = device_create_file(&pdev->dev, &dev_attr_otg_id);
+ if (retval < 0) {
+ otg_dbg(otg,
+ "Can't register sysfs attribute: %d\n", retval);
+ goto exit;
+ }
+#endif
+
return 0;
exit:
if (the_transceiver)