diff options
Diffstat (limited to 'drivers/usb/chipidea')
| -rw-r--r-- | drivers/usb/chipidea/ci_hdrc_msm.c | 24 | ||||
| -rw-r--r-- | drivers/usb/chipidea/core.c | 11 | ||||
| -rw-r--r-- | drivers/usb/chipidea/otg.h | 5 | ||||
| -rw-r--r-- | drivers/usb/chipidea/otg_fsm.c | 69 | ||||
| -rw-r--r-- | drivers/usb/chipidea/udc.c | 22 | ||||
| -rw-r--r-- | drivers/usb/chipidea/usbmisc_imx.c | 10 |
6 files changed, 81 insertions, 60 deletions
diff --git a/drivers/usb/chipidea/ci_hdrc_msm.c b/drivers/usb/chipidea/ci_hdrc_msm.c index 2d51d852b47..d72b9d2de2c 100644 --- a/drivers/usb/chipidea/ci_hdrc_msm.c +++ b/drivers/usb/chipidea/ci_hdrc_msm.c @@ -47,6 +47,7 @@ static void ci_hdrc_msm_notify_event(struct ci_hdrc *ci, unsigned event) static struct ci_hdrc_platform_data ci_hdrc_msm_platdata = { .name = "ci_hdrc_msm", + .capoffset = DEF_CAPOFFSET, .flags = CI_HDRC_REGS_SHARED | CI_HDRC_REQUIRE_TRANSCEIVER | CI_HDRC_DISABLE_STREAMING, @@ -57,9 +58,21 @@ static struct ci_hdrc_platform_data ci_hdrc_msm_platdata = { static int ci_hdrc_msm_probe(struct platform_device *pdev) { struct platform_device *plat_ci; + struct usb_phy *phy; dev_dbg(&pdev->dev, "ci_hdrc_msm_probe\n"); + /* + * OTG(PHY) driver takes care of PHY initialization, clock management, + * powering up VBUS, mapping of registers address space and power + * management. + */ + phy = devm_usb_get_phy_by_phandle(&pdev->dev, "usb-phy", 0); + if (IS_ERR(phy)) + return PTR_ERR(phy); + + ci_hdrc_msm_platdata.phy = phy; + plat_ci = ci_hdrc_add_device(&pdev->dev, pdev->resource, pdev->num_resources, &ci_hdrc_msm_platdata); @@ -86,10 +99,19 @@ static int ci_hdrc_msm_remove(struct platform_device *pdev) return 0; } +static const struct of_device_id msm_ci_dt_match[] = { + { .compatible = "qcom,ci-hdrc", }, + { } +}; +MODULE_DEVICE_TABLE(of, msm_ci_dt_match); + static struct platform_driver ci_hdrc_msm_driver = { .probe = ci_hdrc_msm_probe, .remove = ci_hdrc_msm_remove, - .driver = { .name = "msm_hsusb", }, + .driver = { + .name = "msm_hsusb", + .of_match_table = msm_ci_dt_match, + }, }; module_platform_driver(ci_hdrc_msm_driver); diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c index 128b92ba58a..619d13e2999 100644 --- a/drivers/usb/chipidea/core.c +++ b/drivers/usb/chipidea/core.c @@ -23,7 +23,7 @@ * - BUS: bus glue code, bus abstraction layer * * Compile Options - * - CONFIG_USB_GADGET_DEBUG_FILES: enable debug facilities + * - CONFIG_USB_CHIPIDEA_DEBUG: enable debug facilities * - STALL_IN: non-empty bulk-in pipes cannot be halted * if defined mass storage compliance succeeds but with warnings * => case 4: Hi > Dn @@ -42,9 +42,6 @@ * - Not Supported: 15 & 16 (ISO) * * TODO List - * - Interrupt Traffic - * - GET_STATUS(device) - always reports 0 - * - Gadget API (majority of optional features) * - Suspend & Remote Wakeup */ #include <linux/delay.h> @@ -428,8 +425,7 @@ static irqreturn_t ci_irq(int irq, void *data) ci->id_event = true; /* Clear ID change irq status */ hw_write_otgsc(ci, OTGSC_IDIS, OTGSC_IDIS); - disable_irq_nosync(ci->irq); - queue_work(ci->wq, &ci->work); + ci_otg_queue_work(ci); return IRQ_HANDLED; } @@ -441,8 +437,7 @@ static irqreturn_t ci_irq(int irq, void *data) ci->b_sess_valid_event = true; /* Clear BSV irq */ hw_write_otgsc(ci, OTGSC_BSVIS, OTGSC_BSVIS); - disable_irq_nosync(ci->irq); - queue_work(ci->wq, &ci->work); + ci_otg_queue_work(ci); return IRQ_HANDLED; } diff --git a/drivers/usb/chipidea/otg.h b/drivers/usb/chipidea/otg.h index 73492675411..9ecb598e48f 100644 --- a/drivers/usb/chipidea/otg.h +++ b/drivers/usb/chipidea/otg.h @@ -17,5 +17,10 @@ int ci_hdrc_otg_init(struct ci_hdrc *ci); void ci_hdrc_otg_destroy(struct ci_hdrc *ci); enum ci_role ci_otg_role(struct ci_hdrc *ci); void ci_handle_vbus_change(struct ci_hdrc *ci); +static inline void ci_otg_queue_work(struct ci_hdrc *ci) +{ + disable_irq_nosync(ci->irq); + queue_work(ci->wq, &ci->work); +} #endif /* __DRIVERS_USB_CHIPIDEA_OTG_H */ diff --git a/drivers/usb/chipidea/otg_fsm.c b/drivers/usb/chipidea/otg_fsm.c index 8d4c33dea12..caaabc58021 100644 --- a/drivers/usb/chipidea/otg_fsm.c +++ b/drivers/usb/chipidea/otg_fsm.c @@ -84,8 +84,7 @@ set_a_bus_req(struct device *dev, struct device_attribute *attr, ci->fsm.a_bus_req = 1; } - disable_irq_nosync(ci->irq); - queue_work(ci->wq, &ci->work); + ci_otg_queue_work(ci); mutex_unlock(&ci->fsm.lock); return count; @@ -125,8 +124,7 @@ set_a_bus_drop(struct device *dev, struct device_attribute *attr, ci->fsm.a_bus_req = 0; } - disable_irq_nosync(ci->irq); - queue_work(ci->wq, &ci->work); + ci_otg_queue_work(ci); mutex_unlock(&ci->fsm.lock); return count; @@ -165,8 +163,7 @@ set_b_bus_req(struct device *dev, struct device_attribute *attr, else if (buf[0] == '1') ci->fsm.b_bus_req = 1; - disable_irq_nosync(ci->irq); - queue_work(ci->wq, &ci->work); + ci_otg_queue_work(ci); mutex_unlock(&ci->fsm.lock); return count; @@ -186,8 +183,7 @@ set_a_clr_err(struct device *dev, struct device_attribute *attr, if (buf[0] == '1') ci->fsm.a_clr_err = 1; - disable_irq_nosync(ci->irq); - queue_work(ci->wq, &ci->work); + ci_otg_queue_work(ci); mutex_unlock(&ci->fsm.lock); return count; @@ -297,8 +293,7 @@ static void set_tmout_and_fsm(void *ptr, unsigned long indicator) set_tmout(ci, indicator); - disable_irq_nosync(ci->irq); - queue_work(ci->wq, &ci->work); + ci_otg_queue_work(ci); } static void a_wait_vfall_tmout_func(void *ptr, unsigned long indicator) @@ -312,8 +307,7 @@ static void a_wait_vfall_tmout_func(void *ptr, unsigned long indicator) hw_write_otgsc(ci, OTGSC_DPIS, OTGSC_DPIS); /* Enable data pulse irq */ hw_write_otgsc(ci, OTGSC_DPIE, OTGSC_DPIE); - disable_irq_nosync(ci->irq); - queue_work(ci->wq, &ci->work); + ci_otg_queue_work(ci); } static void b_ase0_brst_tmout_func(void *ptr, unsigned long indicator) @@ -324,8 +318,7 @@ static void b_ase0_brst_tmout_func(void *ptr, unsigned long indicator) if (!hw_read_otgsc(ci, OTGSC_BSV)) ci->fsm.b_sess_vld = 0; - disable_irq_nosync(ci->irq); - queue_work(ci->wq, &ci->work); + ci_otg_queue_work(ci); } static void b_ssend_srp_tmout_func(void *ptr, unsigned long indicator) @@ -335,10 +328,8 @@ static void b_ssend_srp_tmout_func(void *ptr, unsigned long indicator) set_tmout(ci, indicator); /* only vbus fall below B_sess_vld in b_idle state */ - if (ci->transceiver->state == OTG_STATE_B_IDLE) { - disable_irq_nosync(ci->irq); - queue_work(ci->wq, &ci->work); - } + if (ci->transceiver->state == OTG_STATE_B_IDLE) + ci_otg_queue_work(ci); } static void b_sess_vld_tmout_func(void *ptr, unsigned long indicator) @@ -349,8 +340,7 @@ static void b_sess_vld_tmout_func(void *ptr, unsigned long indicator) if (!(hw_read_otgsc(ci, OTGSC_BSV))) { ci->fsm.b_sess_vld = 0; ci_otg_add_timer(ci, B_SSEND_SRP); - disable_irq_nosync(ci->irq); - queue_work(ci->wq, &ci->work); + ci_otg_queue_work(ci); } } @@ -365,8 +355,7 @@ static void b_data_pulse_end(void *ptr, unsigned long indicator) hw_write_otgsc(ci, OTGSC_HABA, 0); - disable_irq_nosync(ci->irq); - queue_work(ci->wq, &ci->work); + ci_otg_queue_work(ci); } /* Initialize timers */ @@ -607,10 +596,8 @@ int ci_otg_fsm_work(struct ci_hdrc *ci) * a_idle to a_wait_vrise when power up */ if ((ci->fsm.id) || (ci->id_event) || - (ci->fsm.power_up)) { - disable_irq_nosync(ci->irq); - queue_work(ci->wq, &ci->work); - } + (ci->fsm.power_up)) + ci_otg_queue_work(ci); if (ci->id_event) ci->id_event = false; } else if (ci->transceiver->state == OTG_STATE_B_IDLE) { @@ -620,8 +607,7 @@ int ci_otg_fsm_work(struct ci_hdrc *ci) * Further transite to b_periphearl state * when register gadget driver with vbus on */ - disable_irq_nosync(ci->irq); - queue_work(ci->wq, &ci->work); + ci_otg_queue_work(ci); } } } @@ -646,22 +632,19 @@ static void ci_otg_fsm_event(struct ci_hdrc *ci) if (port_conn) { fsm->b_conn = 1; fsm->a_bus_req = 1; - disable_irq_nosync(ci->irq); - queue_work(ci->wq, &ci->work); + ci_otg_queue_work(ci); } break; case OTG_STATE_B_IDLE: if (otg_bsess_vld && (intr_sts & USBi_PCI) && port_conn) { fsm->b_sess_vld = 1; - disable_irq_nosync(ci->irq); - queue_work(ci->wq, &ci->work); + ci_otg_queue_work(ci); } break; case OTG_STATE_B_PERIPHERAL: if ((intr_sts & USBi_SLI) && port_conn && otg_bsess_vld) { fsm->a_bus_suspend = 1; - disable_irq_nosync(ci->irq); - queue_work(ci->wq, &ci->work); + ci_otg_queue_work(ci); } else if (intr_sts & USBi_PCI) { if (fsm->a_bus_suspend == 1) fsm->a_bus_suspend = 0; @@ -671,8 +654,7 @@ static void ci_otg_fsm_event(struct ci_hdrc *ci) if ((intr_sts & USBi_PCI) && !port_conn) { fsm->a_conn = 0; fsm->b_bus_req = 0; - disable_irq_nosync(ci->irq); - queue_work(ci->wq, &ci->work); + ci_otg_queue_work(ci); ci_otg_add_timer(ci, B_SESS_VLD); } break; @@ -706,22 +688,19 @@ static void ci_otg_fsm_event(struct ci_hdrc *ci) /* A device to be peripheral mode */ ci->gadget.is_a_peripheral = 1; } - disable_irq_nosync(ci->irq); - queue_work(ci->wq, &ci->work); + ci_otg_queue_work(ci); } break; case OTG_STATE_A_HOST: if ((intr_sts & USBi_PCI) && !port_conn) { fsm->b_conn = 0; - disable_irq_nosync(ci->irq); - queue_work(ci->wq, &ci->work); + ci_otg_queue_work(ci); } break; case OTG_STATE_B_WAIT_ACON: if ((intr_sts & USBi_PCI) && port_conn) { fsm->a_conn = 1; - disable_irq_nosync(ci->irq); - queue_work(ci->wq, &ci->work); + ci_otg_queue_work(ci); } break; default: @@ -782,8 +761,7 @@ irqreturn_t ci_otg_fsm_irq(struct ci_hdrc *ci) fsm->b_conn = 0; } } - disable_irq_nosync(ci->irq); - queue_work(ci->wq, &ci->work); + ci_otg_queue_work(ci); return IRQ_HANDLED; } @@ -794,8 +772,7 @@ irqreturn_t ci_otg_fsm_irq(struct ci_hdrc *ci) void ci_hdrc_otg_fsm_start(struct ci_hdrc *ci) { - disable_irq_nosync(ci->irq); - queue_work(ci->wq, &ci->work); + ci_otg_queue_work(ci); } int ci_hdrc_otg_fsm_init(struct ci_hdrc *ci) diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index 150592f10b3..b8125aa64ad 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c @@ -709,6 +709,8 @@ __acquires(ci->lock) if (ci->status == NULL) retval = -ENOMEM; + usb_gadget_set_state(&ci->gadget, USB_STATE_DEFAULT); + done: spin_lock(&ci->lock); @@ -823,7 +825,6 @@ __acquires(hwep->lock) if ((setup->bRequestType & USB_RECIP_MASK) == USB_RECIP_DEVICE) { /* Assume that device is bus powered for now. */ *(u16 *)req->buf = ci->remote_wakeup << 1; - retval = 0; } else if ((setup->bRequestType & USB_RECIP_MASK) \ == USB_RECIP_ENDPOINT) { dir = (le16_to_cpu(setup->wIndex) & USB_ENDPOINT_DIR_MASK) ? @@ -865,6 +866,8 @@ isr_setup_status_complete(struct usb_ep *ep, struct usb_request *req) if (ci->setaddr) { hw_usb_set_address(ci, ci->address); ci->setaddr = false; + if (ci->address) + usb_gadget_set_state(&ci->gadget, USB_STATE_ADDRESS); } spin_lock_irqsave(&ci->lock, flags); @@ -1166,8 +1169,8 @@ static int ep_enable(struct usb_ep *ep, if (hwep->type == USB_ENDPOINT_XFER_CONTROL) cap |= QH_IOS; - if (hwep->num) - cap |= QH_ZLT; + + cap |= QH_ZLT; cap |= (hwep->ep.maxpacket << __ffs(QH_MAX_PKT)) & QH_MAX_PKT; /* * For ISO-TX, we set mult at QH as the largest value, and use @@ -1318,6 +1321,7 @@ static int ep_dequeue(struct usb_ep *ep, struct usb_request *req) struct ci_hw_ep *hwep = container_of(ep, struct ci_hw_ep, ep); struct ci_hw_req *hwreq = container_of(req, struct ci_hw_req, req); unsigned long flags; + struct td_node *node, *tmpnode; if (ep == NULL || req == NULL || hwreq->req.status != -EALREADY || hwep->ep.desc == NULL || list_empty(&hwreq->queue) || @@ -1328,6 +1332,12 @@ static int ep_dequeue(struct usb_ep *ep, struct usb_request *req) hw_ep_flush(hwep->ci, hwep->num, hwep->dir); + list_for_each_entry_safe(node, tmpnode, &hwreq->tds, td) { + dma_pool_free(hwep->td_pool, node->ptr, node->dma); + list_del(&node->td); + kfree(node); + } + /* pop request */ list_del_init(&hwreq->queue); @@ -1467,7 +1477,7 @@ static int ci_udc_vbus_session(struct usb_gadget *_gadget, int is_active) pm_runtime_get_sync(&_gadget->dev); hw_device_reset(ci, USBMODE_CM_DC); hw_device_state(ci, ci->ep0out->qh.dma); - dev_dbg(ci->dev, "Connected to host\n"); + usb_gadget_set_state(_gadget, USB_STATE_POWERED); } else { if (ci->driver) ci->driver->disconnect(&ci->gadget); @@ -1477,7 +1487,7 @@ static int ci_udc_vbus_session(struct usb_gadget *_gadget, int is_active) CI_HDRC_CONTROLLER_STOPPED_EVENT); _gadget_stop_activity(&ci->gadget); pm_runtime_put_sync(&_gadget->dev); - dev_dbg(ci->dev, "Disconnected from host\n"); + usb_gadget_set_state(_gadget, USB_STATE_NOTATTACHED); } } @@ -1750,6 +1760,8 @@ static irqreturn_t udc_irq(struct ci_hdrc *ci) ci->suspended = 1; spin_unlock(&ci->lock); ci->driver->suspend(&ci->gadget); + usb_gadget_set_state(&ci->gadget, + USB_STATE_SUSPENDED); spin_lock(&ci->lock); } } diff --git a/drivers/usb/chipidea/usbmisc_imx.c b/drivers/usb/chipidea/usbmisc_imx.c index 419b8959d15..85293b8b1df 100644 --- a/drivers/usb/chipidea/usbmisc_imx.c +++ b/drivers/usb/chipidea/usbmisc_imx.c @@ -46,11 +46,14 @@ #define MX27_OTG_PM_BIT BIT(24) #define MX53_USB_OTG_PHY_CTRL_0_OFFSET 0x08 +#define MX53_USB_OTG_PHY_CTRL_1_OFFSET 0x0c #define MX53_USB_UH2_CTRL_OFFSET 0x14 #define MX53_USB_UH3_CTRL_OFFSET 0x18 #define MX53_BM_OVER_CUR_DIS_H1 BIT(5) #define MX53_BM_OVER_CUR_DIS_OTG BIT(8) #define MX53_BM_OVER_CUR_DIS_UHx BIT(30) +#define MX53_USB_PHYCTRL1_PLLDIV_MASK 0x3 +#define MX53_USB_PLL_DIV_24_MHZ 0x01 #define MX6_BM_OVER_CUR_DIS BIT(7) @@ -164,6 +167,13 @@ static int usbmisc_imx53_init(struct imx_usbmisc_data *data) if (data->index > 3) return -EINVAL; + /* Select a 24 MHz reference clock for the PHY */ + reg = usbmisc->base + MX53_USB_OTG_PHY_CTRL_1_OFFSET; + val = readl(reg); + val &= ~MX53_USB_PHYCTRL1_PLLDIV_MASK; + val |= MX53_USB_PLL_DIV_24_MHZ; + writel(val, usbmisc->base + MX53_USB_OTG_PHY_CTRL_1_OFFSET); + if (data->disable_oc) { spin_lock_irqsave(&usbmisc->lock, flags); switch (data->index) { |
