{
struct f_acm *acm = func_to_acm(f);
+ acm_string_defs[ACM_CTRL_IDX].id = 0;
if (gadget_is_dualspeed(c->cdev->gadget))
usb_free_descriptors(f->hs_descriptors);
usb_free_descriptors(f->descriptors);
static void fsg_disable(struct usb_function *f)
{
struct fsg_dev *fsg = fsg_from_func(f);
+ int i;
+ struct fsg_buffhd *bh;
+
+ /* free all of pending request */
+ for (i = 0; i < FSG_NUM_BUFFERS; ++i) {
+ bh = &fsg->common->buffhds[i];
+ if (bh->inreq_busy)
+ usb_ep_dequeue(fsg->bulk_in, bh->inreq);
+ if (bh->outreq_busy)
+ usb_ep_dequeue(fsg->bulk_out, bh->outreq);
+ }
+
fsg->common->new_fsg = NULL;
raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE);
}
{
struct f_rndis *rndis = func_to_rndis(f);
+ rndis_string_defs[0].id = 0;
rndis_deregister(rndis->config);
rndis_exit();
langwell_ep_fifo_flush(&ep->ep);
/* not the last request in endpoint queue */
- if (likely(ep->queue.next == &req->queue)) {
+ if (ep->queue.prev != &req->queue) {
struct langwell_dqh *dqh;
struct langwell_request *next_req;
struct langwell_request, queue);
/* point the dQH to the first dTD of next request */
- writel((u32) next_req->head, &dqh->dqh_current);
}
} else {
struct langwell_request *prev_req;
u32 usbcmd, usbmode, devlc, endpointlistaddr;
u8 devlc_byte0, devlc_byte2;
unsigned long timeout;
+ unsigned long sbuscfg_addr;
if (!dev)
return -EINVAL;
/* Write-Clear setup status */
writel(0, &dev->op_regs->usbsts);
+ /* FIXME: workaround for bug9000364367 */
+ sbuscfg_addr = (unsigned long)dev->cap_regs + SBUSCFG_REG_OFFSET;
+ writel(0x7, sbuscfg_addr);
+
/* if support USB LPM, ACK all LPM token */
if (dev->lpm) {
devlc = readl(&dev->op_regs->devlc);
struct langwell_ep *ep;
dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
- nuke(&dev->ep[0], -ESHUTDOWN);
-
- list_for_each_entry(ep, &dev->gadget.ep_list, ep.ep_list) {
- nuke(ep, -ESHUTDOWN);
- }
-
/* report disconnect; the driver is already quiesced */
if (driver) {
spin_unlock(&dev->lock);
spin_lock(&dev->lock);
}
+ nuke(&dev->ep[0], -ESHUTDOWN);
+
+ list_for_each_entry(ep, &dev->gadget.ep_list, ep.ep_list) {
+ nuke(ep, -ESHUTDOWN);
+ }
+
dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
}
case TEST_J:
case TEST_K:
case TEST_SE0_NAK:
+ langwell_vbus_draw(&dev->gadget, 0);
case TEST_PACKET:
case TEST_FORCE_EN:
portsc1 = readl(&dev->op_regs->portsc1);
/* write 1s to endptflush register to clear any primed buffers */
writel((u32) ~0, &dev->op_regs->endptflush);
- if (readl(&dev->op_regs->portsc1) & PORTS_PR) {
- dev_vdbg(&dev->pdev->dev, "USB bus reset\n");
- /* bus is reseting */
- dev->bus_reset = 1;
-
- /* reset all the queues, stop all USB activities */
- stop_activity(dev, dev->driver);
- dev->usb_state = USB_STATE_DEFAULT;
- } else {
- dev_vdbg(&dev->pdev->dev, "device controller reset\n");
-
- /* add some delay between endpoint flush and controller reset */
- udelay(200);
+ if (!(readl(&dev->op_regs->portsc1) & PORTS_PR))
+ dev_dbg(&dev->pdev->dev, "Intented to reset device controller?\n");
- /* reset all the queues, stop all USB activities */
- stop_activity(dev, dev->driver);
+ /* bus is reseting */
+ dev->bus_reset = 1;
- /* controller reset */
- langwell_udc_reset(dev);
-
- /* reset ep0 dQH and endptctrl */
- ep0_reset(dev);
-
- /* enable interrupt and set controller to run state */
- langwell_udc_start(dev);
-
- dev->usb_state = USB_STATE_ATTACHED;
- }
+ /* reset all the queues, stop all USB activities */
+ stop_activity(dev, dev->driver);
+ dev->usb_state = USB_STATE_DEFAULT;
dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
}
pm_runtime_get_noresume(&pdev->dev);
/* free dTD dma_pool and dQH */
- if (dev->dtd_pool)
+ if (dev->dtd_pool) {
dma_pool_destroy(dev->dtd_pool);
+ dev->dtd_pool = NULL;
+ }
if (dev->ep_dqh)
dma_free_coherent(&pdev->dev, dev->ep_dqh_size,
pci_save_state(pdev);
/* free dTD dma_pool and dQH */
- if (dev->dtd_pool)
+ if (dev->dtd_pool) {
dma_pool_destroy(dev->dtd_pool);
+ dev->dtd_pool = NULL;
+ }
if (dev->ep_dqh)
dma_free_coherent(&pdev->dev, dev->ep_dqh_size,
/* SDP event: enter suspend state */
event = USBCHRG_EVENT_SUSPEND;
flag = 1;
+ } else if (mA == 0) {
+ event = USBCHRG_EVENT_DISCONN;
+ flag = 1;
} else
dev_dbg(pnw->dev, "SDP: no need to update EM\n");
break;
}
/* manual charger detection by ULPI access */
-static int penwell_otg_manual_charger_detection(void)
+static int penwell_otg_manual_chrg_det(void)
{
struct penwell_otg *pnw = the_transceiver;
struct intel_mid_otg_xceiv *iotg;
if (!is_clovertrail(pdev)) {
mutex_lock(&pnw->msic_mutex);
if (pdev->revision >= 0x8) {
- retval =
- penwell_otg_manual_charger_detection();
+ retval = penwell_otg_manual_chrg_det();
+ if (retval < 0) {
+ /* if failed, reset controller
+ * and try charger detection
+ * flow again */
+ dev_warn(pnw->dev,
+ "detection failed, retry");
+ set_client_mode();
+ msleep(100);
+ penwell_otg_phy_low_power(0);
+ retval = penwell_otg_manual_chrg_det();
+ }
} else {
/* Enable data contact detection */
penwell_otg_data_contact_detect();
return PAGE_SIZE - size;
}
-static DEVICE_ATTR(hsm, S_IRUGO, show_hsm, NULL);
+static DEVICE_ATTR(hsm, S_IRUGO | S_IWUSR | S_IWGRP, show_hsm, NULL);
static ssize_t
show_chargers(struct device *_dev, struct device_attribute *attr, char *buf)
return count;
}
-static DEVICE_ATTR(a_bus_req, S_IRUGO | S_IWUGO, get_a_bus_req, set_a_bus_req);
+static DEVICE_ATTR(a_bus_req, S_IRUGO | S_IWUSR | S_IWGRP,
+ get_a_bus_req, set_a_bus_req);
static ssize_t
get_a_bus_drop(struct device *dev, struct device_attribute *attr, char *buf)
return count;
}
-static DEVICE_ATTR(a_bus_drop, S_IRUGO | S_IWUGO,
+static DEVICE_ATTR(a_bus_drop, S_IRUGO | S_IWUSR | S_IWGRP,
get_a_bus_drop, set_a_bus_drop);
static ssize_t
return count;
}
-static DEVICE_ATTR(b_bus_req, S_IRUGO | S_IWUGO, get_b_bus_req, set_b_bus_req);
+static DEVICE_ATTR(b_bus_req, S_IRUGO | S_IWUSR | S_IWGRP,
+ get_b_bus_req, set_b_bus_req);
static ssize_t
set_a_clr_err(struct device *dev, struct device_attribute *attr,
return count;
}
-static DEVICE_ATTR(a_clr_err, S_IWUGO, NULL, set_a_clr_err);
+static DEVICE_ATTR(a_clr_err, S_IRUGO | S_IWUSR | S_IWGRP, NULL, set_a_clr_err);
static struct attribute *inputs_attrs[] = {
&dev_attr_a_bus_req.attr,
#define CAP_REG_OFFSET 0x0
#define OP_REG_OFFSET 0x28
+#define SBUSCFG_REG_OFFSET 0x290
+
#define DMA_ADDR_INVALID (~(dma_addr_t)0)
#define DQH_ALIGNMENT 2048