diff options
Diffstat (limited to 'drivers/usb/dwc2/gadget.c')
-rw-r--r-- | drivers/usb/dwc2/gadget.c | 94 |
1 files changed, 26 insertions, 68 deletions
diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index af46adfae41c..4cd6403a7566 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c @@ -186,9 +186,10 @@ static void dwc2_hsotg_ctrl_epint(struct dwc2_hsotg *hsotg, */ static void dwc2_hsotg_init_fifo(struct dwc2_hsotg *hsotg) { - unsigned int ep; + unsigned int fifo; unsigned int addr; int timeout; + u32 dptxfsizn; u32 val; /* Reset fifo map if not correctly cleared during previous session */ @@ -216,16 +217,16 @@ static void dwc2_hsotg_init_fifo(struct dwc2_hsotg *hsotg) * them to endpoints dynamically according to maxpacket size value of * given endpoint. */ - for (ep = 1; ep < MAX_EPS_CHANNELS; ep++) { - if (!hsotg->g_tx_fifo_sz[ep]) - continue; - val = addr; - val |= hsotg->g_tx_fifo_sz[ep] << FIFOSIZE_DEPTH_SHIFT; - WARN_ONCE(addr + hsotg->g_tx_fifo_sz[ep] > hsotg->fifo_mem, - "insufficient fifo memory"); - addr += hsotg->g_tx_fifo_sz[ep]; + for (fifo = 1; fifo < MAX_EPS_CHANNELS; fifo++) { + dptxfsizn = dwc2_readl(hsotg->regs + DPTXFSIZN(fifo)); + + val = (dptxfsizn & FIFOSIZE_DEPTH_MASK) | addr; + addr += dptxfsizn >> FIFOSIZE_DEPTH_SHIFT; + + if (addr > hsotg->fifo_mem) + break; - dwc2_writel(val, hsotg->regs + DPTXFSIZN(ep)); + dwc2_writel(val, hsotg->regs + DPTXFSIZN(fifo)); } /* @@ -388,7 +389,8 @@ static int dwc2_hsotg_write_fifo(struct dwc2_hsotg *hsotg, return -ENOSPC; } } else if (hsotg->dedicated_fifos && hs_ep->index != 0) { - can_write = dwc2_readl(hsotg->regs + DTXFSTS(hs_ep->index)); + can_write = dwc2_readl(hsotg->regs + + DTXFSTS(hs_ep->fifo_index)); can_write &= 0xffff; can_write *= 4; @@ -2432,7 +2434,7 @@ static void kill_all_requests(struct dwc2_hsotg *hsotg, if (!hsotg->dedicated_fifos) return; - size = (dwc2_readl(hsotg->regs + DTXFSTS(ep->index)) & 0xffff) * 4; + size = (dwc2_readl(hsotg->regs + DTXFSTS(ep->fifo_index)) & 0xffff) * 4; if (size < ep->fifo_size) dwc2_hsotg_txfifo_flush(hsotg, ep->fifo_index); } @@ -3041,22 +3043,11 @@ static int dwc2_hsotg_ep_enable(struct usb_ep *ep, break; } - /* If fifo is already allocated for this ep */ - if (hs_ep->fifo_index) { - size = hs_ep->ep.maxpacket * hs_ep->mc; - /* If bigger fifo is required deallocate current one */ - if (size > hs_ep->fifo_size) { - hsotg->fifo_map &= ~(1 << hs_ep->fifo_index); - hs_ep->fifo_index = 0; - hs_ep->fifo_size = 0; - } - } - /* * if the hardware has dedicated fifos, we must give each IN EP * a unique tx-fifo even if it is non-periodic. */ - if (dir_in && hsotg->dedicated_fifos && !hs_ep->fifo_index) { + if (dir_in && hsotg->dedicated_fifos) { u32 fifo_index = 0; u32 fifo_size = UINT_MAX; size = hs_ep->ep.maxpacket*hs_ep->mc; @@ -3129,10 +3120,6 @@ static int dwc2_hsotg_ep_disable(struct usb_ep *ep) spin_lock_irqsave(&hsotg->lock, flags); - hsotg->fifo_map &= ~(1<<hs_ep->fifo_index); - hs_ep->fifo_index = 0; - hs_ep->fifo_size = 0; - ctrl = dwc2_readl(hsotg->regs + epctrl_reg); ctrl &= ~DXEPCTL_EPENA; ctrl &= ~DXEPCTL_USBACTEP; @@ -3147,6 +3134,10 @@ static int dwc2_hsotg_ep_disable(struct usb_ep *ep) /* terminate all requests with shutdown */ kill_all_requests(hsotg, hs_ep, -ESHUTDOWN); + hsotg->fifo_map &= ~(1 << hs_ep->fifo_index); + hs_ep->fifo_index = 0; + hs_ep->fifo_size = 0; + spin_unlock_irqrestore(&hsotg->lock, flags); return 0; } @@ -3475,8 +3466,11 @@ static int dwc2_hsotg_udc_start(struct usb_gadget *gadget, otg_set_peripheral(hsotg->uphy->otg, &hsotg->gadget); spin_lock_irqsave(&hsotg->lock, flags); - dwc2_hsotg_init(hsotg); - dwc2_hsotg_core_init_disconnected(hsotg, false); + if (dwc2_hw_is_device(hsotg)) { + dwc2_hsotg_init(hsotg); + dwc2_hsotg_core_init_disconnected(hsotg, false); + } + hsotg->enabled = 0; spin_unlock_irqrestore(&hsotg->lock, flags); @@ -3813,36 +3807,10 @@ static void dwc2_hsotg_dump(struct dwc2_hsotg *hsotg) static void dwc2_hsotg_of_probe(struct dwc2_hsotg *hsotg) { struct device_node *np = hsotg->dev->of_node; - u32 len = 0; - u32 i = 0; /* Enable dma if requested in device tree */ hsotg->g_using_dma = of_property_read_bool(np, "g-use-dma"); - /* - * Register TX periodic fifo size per endpoint. - * EP0 is excluded since it has no fifo configuration. - */ - if (!of_find_property(np, "g-tx-fifo-size", &len)) - goto rx_fifo; - - len /= sizeof(u32); - - /* Read tx fifo sizes other than ep0 */ - if (of_property_read_u32_array(np, "g-tx-fifo-size", - &hsotg->g_tx_fifo_sz[1], len)) - goto rx_fifo; - - /* Add ep0 */ - len++; - - /* Make remaining TX fifos unavailable */ - if (len < MAX_EPS_CHANNELS) { - for (i = len; i < MAX_EPS_CHANNELS; i++) - hsotg->g_tx_fifo_sz[i] = 0; - } - -rx_fifo: /* Register RX fifo size */ of_property_read_u32(np, "g-rx-fifo-size", &hsotg->g_rx_fifo_sz); @@ -3864,13 +3832,10 @@ int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq) struct device *dev = hsotg->dev; int epnum; int ret; - int i; - u32 p_tx_fifo[] = DWC2_G_P_LEGACY_TX_FIFO_SIZE; /* Initialize to legacy fifo configuration values */ hsotg->g_rx_fifo_sz = 2048; hsotg->g_np_g_tx_fifo_sz = 1024; - memcpy(&hsotg->g_tx_fifo_sz[1], p_tx_fifo, sizeof(p_tx_fifo)); /* Device tree specific probe */ dwc2_hsotg_of_probe(hsotg); @@ -3888,9 +3853,6 @@ int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq) dev_dbg(dev, "NonPeriodic TXFIFO size: %d\n", hsotg->g_np_g_tx_fifo_sz); dev_dbg(dev, "RXFIFO size: %d\n", hsotg->g_rx_fifo_sz); - for (i = 0; i < MAX_EPS_CHANNELS; i++) - dev_dbg(dev, "Periodic TXFIFO%2d size: %d\n", i, - hsotg->g_tx_fifo_sz[i]); hsotg->gadget.max_speed = USB_SPEED_HIGH; hsotg->gadget.ops = &dwc2_hsotg_gadget_ops; @@ -3908,17 +3870,13 @@ int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq) hsotg->ctrl_buff = devm_kzalloc(hsotg->dev, DWC2_CTRL_BUFF_SIZE, GFP_KERNEL); - if (!hsotg->ctrl_buff) { - dev_err(dev, "failed to allocate ctrl request buff\n"); + if (!hsotg->ctrl_buff) return -ENOMEM; - } hsotg->ep0_buff = devm_kzalloc(hsotg->dev, DWC2_CTRL_BUFF_SIZE, GFP_KERNEL); - if (!hsotg->ep0_buff) { - dev_err(dev, "failed to allocate ctrl reply buff\n"); + if (!hsotg->ep0_buff) return -ENOMEM; - } ret = devm_request_irq(hsotg->dev, irq, dwc2_hsotg_irq, IRQF_SHARED, dev_name(hsotg->dev), hsotg); |