From 66b76dbe37df88b250ffdac186adba3e5dc24631 Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Sat, 9 Jul 2016 14:16:38 +0000 Subject: usb: chipidea: udc: move write barrier into hw_ep_prime Since there should be a write barrier before every call of hw_ep_prime we could move it into hw_ep_prime. Signed-off-by: Stefan Wahren Signed-off-by: Peter Chen --- drivers/usb/chipidea/udc.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index b93356834bb5..b0c4ae1cd206 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c @@ -188,6 +188,9 @@ static int hw_ep_prime(struct ci_hdrc *ci, int num, int dir, int is_ctrl) { int n = hw_ep_bit(num, dir); + /* Synchronize before ep prime */ + wmb(); + if (is_ctrl && dir == RX && hw_read(ci, OP_ENDPTSETUPSTAT, BIT(num))) return -EAGAIN; @@ -506,8 +509,6 @@ static int _hardware_enqueue(struct ci_hw_ep *hwep, struct ci_hw_req *hwreq) hwep->qh.ptr->cap |= mul << __ffs(QH_MULT); } - wmb(); /* synchronize before ep prime */ - ret = hw_ep_prime(ci, hwep->num, hwep->dir, hwep->type == USB_ENDPOINT_XFER_CONTROL); done: @@ -534,9 +535,6 @@ static int reprime_dtd(struct ci_hdrc *ci, struct ci_hw_ep *hwep, hwep->qh.ptr->td.token &= cpu_to_le32(~(TD_STATUS_HALTED | TD_STATUS_ACTIVE)); - /* Synchronize before ep prime */ - wmb(); - return hw_ep_prime(ci, hwep->num, hwep->dir, hwep->type == USB_ENDPOINT_XFER_CONTROL); } -- cgit v1.2.3 From 8007eb4e1824e52483ad99fb229fc56e6a73cec6 Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Sat, 9 Jul 2016 14:16:39 +0000 Subject: usb: chipidea: udc: Don't flush endpoint fifo twice The endpoint fifo is already flushed in _ep_nuke so there is no need to flush it twice. Signed-off-by: Stefan Wahren Signed-off-by: Peter Chen --- drivers/usb/chipidea/udc.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/usb') diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index b0c4ae1cd206..a66a47a9d2a7 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c @@ -121,7 +121,6 @@ static int hw_ep_flush(struct ci_hdrc *ci, int num, int dir) */ static int hw_ep_disable(struct ci_hdrc *ci, int num, int dir) { - hw_ep_flush(ci, num, dir); hw_write(ci, OP_ENDPTCTRL + num, dir ? ENDPTCTRL_TXE : ENDPTCTRL_RXE, 0); return 0; -- cgit v1.2.3 From 9dba516ed282e3d16481051be547b54caa312029 Mon Sep 17 00:00:00 2001 From: Li Jun Date: Wed, 20 Jul 2016 16:02:42 +0800 Subject: usb: chipidea: imx: set over current polarity per dts setting imx usb over current polarity is low active by default, with over-current-active-high property added, user can config it to be high active. Meanwhile keep this setting unchanged for existing platforms so new platform must set the right value for active low by its usbmisc init function if over current is enabled. Signed-off-by: Li Jun Signed-off-by: Peter Chen --- drivers/usb/chipidea/ci_hdrc_imx.c | 3 +++ drivers/usb/chipidea/ci_hdrc_imx.h | 1 + drivers/usb/chipidea/usbmisc_imx.c | 22 +++++++++++++++++----- 3 files changed, 21 insertions(+), 5 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c index dedc33e589f4..099179457f60 100644 --- a/drivers/usb/chipidea/ci_hdrc_imx.c +++ b/drivers/usb/chipidea/ci_hdrc_imx.c @@ -140,6 +140,9 @@ static struct imx_usbmisc_data *usbmisc_get_init_data(struct device *dev) if (of_find_property(np, "disable-over-current", NULL)) data->disable_oc = 1; + if (of_find_property(np, "over-current-active-high", NULL)) + data->oc_polarity = 1; + if (of_find_property(np, "external-vbus-divider", NULL)) data->evdo = 1; diff --git a/drivers/usb/chipidea/ci_hdrc_imx.h b/drivers/usb/chipidea/ci_hdrc_imx.h index 635717e9354a..409aa5ca8dda 100644 --- a/drivers/usb/chipidea/ci_hdrc_imx.h +++ b/drivers/usb/chipidea/ci_hdrc_imx.h @@ -17,6 +17,7 @@ struct imx_usbmisc_data { int index; unsigned int disable_oc:1; /* over current detect disabled */ + unsigned int oc_polarity:1; /* over current polarity if oc enabled */ unsigned int evdo:1; /* set external vbus divider option */ }; diff --git a/drivers/usb/chipidea/usbmisc_imx.c b/drivers/usb/chipidea/usbmisc_imx.c index ab8b027e8cc8..20d02a5e418d 100644 --- a/drivers/usb/chipidea/usbmisc_imx.c +++ b/drivers/usb/chipidea/usbmisc_imx.c @@ -56,6 +56,7 @@ #define MX6_BM_NON_BURST_SETTING BIT(1) #define MX6_BM_OVER_CUR_DIS BIT(7) +#define MX6_BM_OVER_CUR_POLARITY BIT(8) #define MX6_BM_WAKEUP_ENABLE BIT(10) #define MX6_BM_ID_WAKEUP BIT(16) #define MX6_BM_VBUS_WAKEUP BIT(17) @@ -266,11 +267,14 @@ static int usbmisc_imx6q_init(struct imx_usbmisc_data *data) spin_lock_irqsave(&usbmisc->lock, flags); + reg = readl(usbmisc->base + data->index * 4); if (data->disable_oc) { - reg = readl(usbmisc->base + data->index * 4); - writel(reg | MX6_BM_OVER_CUR_DIS, - usbmisc->base + data->index * 4); + reg |= MX6_BM_OVER_CUR_DIS; + } else if (data->oc_polarity == 1) { + /* High active */ + reg &= ~(MX6_BM_OVER_CUR_DIS | MX6_BM_OVER_CUR_POLARITY); } + writel(reg, usbmisc->base + data->index * 4); /* SoC non-burst setting */ reg = readl(usbmisc->base + data->index * 4); @@ -365,10 +369,14 @@ static int usbmisc_imx7d_init(struct imx_usbmisc_data *data) return -EINVAL; spin_lock_irqsave(&usbmisc->lock, flags); + reg = readl(usbmisc->base); if (data->disable_oc) { - reg = readl(usbmisc->base); - writel(reg | MX6_BM_OVER_CUR_DIS, usbmisc->base); + reg |= MX6_BM_OVER_CUR_DIS; + } else if (data->oc_polarity == 1) { + /* High active */ + reg &= ~(MX6_BM_OVER_CUR_DIS | MX6_BM_OVER_CUR_POLARITY); } + writel(reg, usbmisc->base); reg = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2); reg &= ~MX7D_USB_VBUS_WAKEUP_SOURCE_MASK; @@ -492,6 +500,10 @@ static const struct of_device_id usbmisc_imx_dt_ids[] = { .compatible = "fsl,imx6ul-usbmisc", .data = &imx6sx_usbmisc_ops, }, + { + .compatible = "fsl,imx7d-usbmisc", + .data = &imx7d_usbmisc_ops, + }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, usbmisc_imx_dt_ids); -- cgit v1.2.3 From c6ee9f2345a2d95a986309a6486ae780f563230a Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Thu, 11 Aug 2016 17:19:13 +0000 Subject: usb: chipidea: udc: Use direction flags consequently This driver make assumptions about the value of the direction flags. So better use them in comparisons to improve the readability. Signed-off-by: Stefan Wahren Signed-off-by: Peter Chen --- drivers/usb/chipidea/udc.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index a66a47a9d2a7..c1eea62ab998 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c @@ -59,7 +59,7 @@ ctrl_endpt_in_desc = { */ static inline int hw_ep_bit(int num, int dir) { - return num + (dir ? 16 : 0); + return num + ((dir == TX) ? 16 : 0); } static inline int ep_to_bit(struct ci_hdrc *ci, int n) @@ -122,7 +122,7 @@ static int hw_ep_flush(struct ci_hdrc *ci, int num, int dir) static int hw_ep_disable(struct ci_hdrc *ci, int num, int dir) { hw_write(ci, OP_ENDPTCTRL + num, - dir ? ENDPTCTRL_TXE : ENDPTCTRL_RXE, 0); + (dir == TX) ? ENDPTCTRL_TXE : ENDPTCTRL_RXE, 0); return 0; } @@ -138,7 +138,7 @@ static int hw_ep_enable(struct ci_hdrc *ci, int num, int dir, int type) { u32 mask, data; - if (dir) { + if (dir == TX) { mask = ENDPTCTRL_TXT; /* type */ data = type << __ffs(mask); @@ -170,7 +170,7 @@ static int hw_ep_enable(struct ci_hdrc *ci, int num, int dir, int type) */ static int hw_ep_get_halt(struct ci_hdrc *ci, int num, int dir) { - u32 mask = dir ? ENDPTCTRL_TXS : ENDPTCTRL_RXS; + u32 mask = (dir == TX) ? ENDPTCTRL_TXS : ENDPTCTRL_RXS; return hw_read(ci, OP_ENDPTCTRL + num, mask) ? 1 : 0; } @@ -220,8 +220,8 @@ static int hw_ep_set_halt(struct ci_hdrc *ci, int num, int dir, int value) do { enum ci_hw_regs reg = OP_ENDPTCTRL + num; - u32 mask_xs = dir ? ENDPTCTRL_TXS : ENDPTCTRL_RXS; - u32 mask_xr = dir ? ENDPTCTRL_TXR : ENDPTCTRL_RXR; + u32 mask_xs = (dir == TX) ? ENDPTCTRL_TXS : ENDPTCTRL_RXS; + u32 mask_xr = (dir == TX) ? ENDPTCTRL_TXR : ENDPTCTRL_RXR; /* data toggle - reserved for EP0 but it's in ESS */ hw_write(ci, reg, mask_xs|mask_xr, @@ -587,7 +587,7 @@ static int _hardware_dequeue(struct ci_hw_ep *hwep, struct ci_hw_req *hwreq) } if (remaining_length) { - if (hwep->dir) { + if (hwep->dir == TX) { hwreq->req.status = -EPROTO; break; } @@ -1048,9 +1048,9 @@ __acquires(ci->lock) if (req.wLength != 0) break; num = le16_to_cpu(req.wIndex); - dir = num & USB_ENDPOINT_DIR_MASK; + dir = (num & USB_ENDPOINT_DIR_MASK) ? TX : RX; num &= USB_ENDPOINT_NUMBER_MASK; - if (dir) /* TX */ + if (dir == TX) num += ci->hw_ep_max / 2; if (!ci->ci_hw_ep[num].wedge) { spin_unlock(&ci->lock); @@ -1100,9 +1100,9 @@ __acquires(ci->lock) if (req.wLength != 0) break; num = le16_to_cpu(req.wIndex); - dir = num & USB_ENDPOINT_DIR_MASK; + dir = (num & USB_ENDPOINT_DIR_MASK) ? TX : RX; num &= USB_ENDPOINT_NUMBER_MASK; - if (dir) /* TX */ + if (dir == TX) num += ci->hw_ep_max / 2; spin_unlock(&ci->lock); -- cgit v1.2.3 From c744a0db756b34c7e2b60100bcfc58beb6b68c99 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Mon, 15 Aug 2016 16:09:07 +0200 Subject: usb: chipidea: host: disable io watchdog The Chipidea EHCI core seems to behave sanely and doesn't need the IO watchdog. This kills off 10 non-deferrable wakeup events per second when the controller is otherwise idle. Signed-off-by: Lucas Stach Tested-by: Stefan Agner Signed-off-by: Peter Chen --- drivers/usb/chipidea/host.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c index 053bac9d983c..96ae69502c86 100644 --- a/drivers/usb/chipidea/host.c +++ b/drivers/usb/chipidea/host.c @@ -81,12 +81,15 @@ static int ehci_ci_reset(struct usb_hcd *hcd) { struct device *dev = hcd->self.controller; struct ci_hdrc *ci = dev_get_drvdata(dev); + struct ehci_hcd *ehci = hcd_to_ehci(hcd); int ret; ret = ehci_setup(hcd); if (ret) return ret; + ehci->need_io_watchdog = 0; + ci_platform_configure(ci); return ret; -- cgit v1.2.3 From 382c1b38d8e70b2fe239c96bb9137c10f3229ba3 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Thu, 8 Sep 2016 09:34:30 -0300 Subject: usb: chipidea: udc: Use dma_pool_zalloc() We can make the code simpler by using dma_pool_zalloc() instead of calling dma_pool_alloc() and then a memset(). Signed-off-by: Fabio Estevam Signed-off-by: Peter Chen --- drivers/usb/chipidea/udc.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index c1eea62ab998..a0b208dfb959 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c @@ -1677,12 +1677,10 @@ static int init_eps(struct ci_hdrc *ci) usb_ep_set_maxpacket_limit(&hwep->ep, (unsigned short)~0); INIT_LIST_HEAD(&hwep->qh.queue); - hwep->qh.ptr = dma_pool_alloc(ci->qh_pool, GFP_KERNEL, - &hwep->qh.dma); + hwep->qh.ptr = dma_pool_zalloc(ci->qh_pool, GFP_KERNEL, + &hwep->qh.dma); if (hwep->qh.ptr == NULL) retval = -ENOMEM; - else - memset(hwep->qh.ptr, 0, sizeof(*hwep->qh.ptr)); /* * set up shorthands for ep0 out and in endpoints, -- cgit v1.2.3 From 58001effe172f300d558dffbd723c8521b9404f2 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Thu, 8 Sep 2016 09:34:31 -0300 Subject: usb: chipidea: udc: Fit into a single line No need to split the dma_pool_zalloc() line into two as it can perfectly fit into a single line. Signed-off-by: Fabio Estevam Signed-off-by: Peter Chen --- drivers/usb/chipidea/udc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index a0b208dfb959..22534a1622d9 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c @@ -350,8 +350,7 @@ static int add_td_to_list(struct ci_hw_ep *hwep, struct ci_hw_req *hwreq, if (node == NULL) return -ENOMEM; - node->ptr = dma_pool_zalloc(hwep->td_pool, GFP_ATOMIC, - &node->dma); + node->ptr = dma_pool_zalloc(hwep->td_pool, GFP_ATOMIC, &node->dma); if (node->ptr == NULL) { kfree(node); return -ENOMEM; -- cgit v1.2.3 From e74e83724808b72173b557bd8008202109fb6091 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Thu, 8 Sep 2016 09:34:32 -0300 Subject: usb: chipidea: udc: Use the preferred form for passing a size of a struct According to Documentation/CodingStyle: "The preferred form for passing a size of a struct is the following: p = kmalloc(sizeof(*p), ...); " , so do as suggested to improve readability. Signed-off-by: Fabio Estevam Signed-off-by: Peter Chen --- drivers/usb/chipidea/udc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/usb') diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index 22534a1622d9..661f43fe0f9e 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c @@ -1993,7 +1993,7 @@ int ci_hdrc_gadget_init(struct ci_hdrc *ci) if (!hw_read(ci, CAP_DCCPARAMS, DCCPARAMS_DC)) return -ENXIO; - rdrv = devm_kzalloc(ci->dev, sizeof(struct ci_role_driver), GFP_KERNEL); + rdrv = devm_kzalloc(ci->dev, sizeof(*rdrv), GFP_KERNEL); if (!rdrv) return -ENOMEM; -- cgit v1.2.3