/** * dwc3_otg_set_peripheral - bind/unbind the peripheral controller driver. * * Returns 0 on success otherwise negative errno. */ static int dwc3_otg_set_peripheral(struct usb_otg *otg, struct usb_gadget *gadget) { struct dwc3_otg *dotg = container_of(otg, struct dwc3_otg, otg); struct otg_fsm *fsm = &dotg->fsm; struct device *dev = dotg->dwc->dev; if (gadget) { dev_err(dev, "Binding gadget %s\n", gadget->name); otg->gadget = gadget; } else { dev_err(dev, "Unbinding gadget\n"); mutex_lock(&fsm->lock); if (otg->phy->state == OTG_STATE_B_PERIPHERAL) { /* Reset OTG SM */ fsm->reset = 1; dwc3_otg_statemachine(fsm); fsm->reset = 0; } otg->gadget = NULL; mutex_unlock(&fsm->lock); dwc3_otg_run_sm(fsm); } return 0; }
static irqreturn_t dwc3_otg_thread_interrupt(int irq, void *_dotg) { struct dwc3_otg *dotg = (struct dwc3_otg *)_dotg; dwc3_otg_run_sm(&dotg->fsm); return IRQ_HANDLED; }
static ssize_t dwc3_otg_store_id(struct device *dev, struct device_attribute *attr, const char *buf, size_t n) { struct dwc3 *dwc = dev_get_drvdata(dev); struct otg_fsm *fsm = &dwc->dotg->fsm; int id; if (sscanf(buf, "%d", &id) != 1) return -EINVAL; fsm->id = !!id; dwc3_otg_run_sm(fsm); return n; }
/** * dwc3_otg_start * @dwc: pointer to our controller context structure */ int dwc3_otg_start(struct dwc3 *dwc) { struct dwc3_otg *dotg = dwc->dotg; struct otg_fsm *fsm = &dotg->fsm; int ret; if (dotg->ext_otg_ops) { ret = dwc3_ext_otg_start(dotg); if (ret) { dev_err(dwc->dev, "failed to start external OTG\n"); return ret; } } else { dotg->regs = dwc->regs; dwc3_otg_reset(dotg); dotg->fsm.id = dwc3_otg_get_id_state(dotg); dotg->fsm.b_sess_vld = dwc3_otg_get_b_sess_state(dotg); dotg->irq = platform_get_irq(to_platform_device(dwc->dev), 0); ret = devm_request_threaded_irq(dwc->dev, dotg->irq, dwc3_otg_interrupt, dwc3_otg_thread_interrupt, IRQF_SHARED, "dwc3-otg", dotg); if (ret) { dev_err(dwc->dev, "failed to request irq #%d --> %d\n", dotg->irq, ret); return ret; } dwc3_otg_enable_irq(dotg); } dotg->ready = 1; dwc3_otg_run_sm(fsm); return 0; }