Merge tag 'dwc3-for-v3.4' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi...
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 2 Mar 2012 23:56:33 +0000 (15:56 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 2 Mar 2012 23:56:33 +0000 (15:56 -0800)
usb: dwc3: changes for v3.4 merge window

Here are the changes for v3.4 merge window.

It includes a new glue layer for Samsung's Exynos platform, a simplification of
memory management on DWC3 driver by using dev_xxx functions, a few
optimizations to IRQ handling by dropping memcpy() and using bitshifts, a fix
for TI's OMAP5430 TX Fifo Allocation, two fixes on USB2 test mode
implementation (one on debugfs and one on ep0), and several minor changes such
as whitespace cleanups, simplification of a few parts of the code, decreasing a
long delay to something a bit saner, dropping a header which was included twice
and so on.

The highlight on this merge is the support for Samsung's Exynos platform,
increasing the number of different users for this driver to three.

Note that Samsung Exynos glue layer will only compile on platforms which
provide implementation for the clk API for now. Once Samsung supports
pm_runtime, that limitation can be dropped from the Makefile.

Conflicts:
drivers/usb/dwc3/gadget.c

1  2 
drivers/usb/dwc3/core.h
drivers/usb/dwc3/ep0.c
drivers/usb/dwc3/gadget.c
drivers/usb/dwc3/gadget.h

Simple merge
Simple merge
  #include "gadget.h"
  #include "io.h"
  
 -#define       DMA_ADDR_INVALID        (~(dma_addr_t)0)
 -
+ /**
+  * dwc3_gadget_set_test_mode - Enables USB2 Test Modes
+  * @dwc: pointer to our context structure
+  * @mode: the mode to set (J, K SE0 NAK, Force Enable)
+  *
+  * Caller should take care of locking. This function will
+  * return 0 on success or -EINVAL if wrong Test Selector
+  * is passed
+  */
+ int dwc3_gadget_set_test_mode(struct dwc3 *dwc, int mode)
+ {
+       u32             reg;
+       reg = dwc3_readl(dwc->regs, DWC3_DCTL);
+       reg &= ~DWC3_DCTL_TSTCTRL_MASK;
+       switch (mode) {
+       case TEST_J:
+       case TEST_K:
+       case TEST_SE0_NAK:
+       case TEST_PACKET:
+       case TEST_FORCE_EN:
+               reg |= mode << 1;
+               break;
+       default:
+               return -EINVAL;
+       }
+       dwc3_writel(dwc->regs, DWC3_DCTL, reg);
+       return 0;
+ }
+ /**
+  * dwc3_gadget_set_link_state - Sets USB Link to a particular State
+  * @dwc: pointer to our context structure
+  * @state: the state to put link into
+  *
+  * Caller should take care of locking. This function will
+  * return 0 on success or -ETIMEDOUT.
+  */
+ int dwc3_gadget_set_link_state(struct dwc3 *dwc, enum dwc3_link_state state)
+ {
+       int             retries = 10000;
+       u32             reg;
+       reg = dwc3_readl(dwc->regs, DWC3_DCTL);
+       reg &= ~DWC3_DCTL_ULSTCHNGREQ_MASK;
+       /* set requested state */
+       reg |= DWC3_DCTL_ULSTCHNGREQ(state);
+       dwc3_writel(dwc->regs, DWC3_DCTL, reg);
+       /* wait for a change in DSTS */
+       while (--retries) {
+               reg = dwc3_readl(dwc->regs, DWC3_DSTS);
+               if (DWC3_DSTS_USBLNKST(reg) == state)
+                       return 0;
+               udelay(5);
+       }
+       dev_vdbg(dwc->dev, "link state change request timed out\n");
+       return -ETIMEDOUT;
+ }
+ /**
+  * dwc3_gadget_resize_tx_fifos - reallocate fifo spaces for current use-case
+  * @dwc: pointer to our context structure
+  *
+  * This function will a best effort FIFO allocation in order
+  * to improve FIFO usage and throughput, while still allowing
+  * us to enable as many endpoints as possible.
+  *
+  * Keep in mind that this operation will be highly dependent
+  * on the configured size for RAM1 - which contains TxFifo -,
+  * the amount of endpoints enabled on coreConsultant tool, and
+  * the width of the Master Bus.
+  *
+  * In the ideal world, we would always be able to satisfy the
+  * following equation:
+  *
+  * ((512 + 2 * MDWIDTH-Bytes) + (Number of IN Endpoints - 1) * \
+  * (3 * (1024 + MDWIDTH-Bytes) + MDWIDTH-Bytes)) / MDWIDTH-Bytes
+  *
+  * Unfortunately, due to many variables that's not always the case.
+  */
+ int dwc3_gadget_resize_tx_fifos(struct dwc3 *dwc)
+ {
+       int             last_fifo_depth = 0;
+       int             ram1_depth;
+       int             fifo_size;
+       int             mdwidth;
+       int             num;
+       if (!dwc->needs_fifo_resize)
+               return 0;
+       ram1_depth = DWC3_RAM1_DEPTH(dwc->hwparams.hwparams7);
+       mdwidth = DWC3_MDWIDTH(dwc->hwparams.hwparams0);
+       /* MDWIDTH is represented in bits, we need it in bytes */
+       mdwidth >>= 3;
+       /*
+        * FIXME For now we will only allocate 1 wMaxPacketSize space
+        * for each enabled endpoint, later patches will come to
+        * improve this algorithm so that we better use the internal
+        * FIFO space
+        */
+       for (num = 0; num < DWC3_ENDPOINTS_NUM; num++) {
+               struct dwc3_ep  *dep = dwc->eps[num];
+               int             fifo_number = dep->number >> 1;
+               int             mult = 1;
+               int             tmp;
+               if (!(dep->number & 1))
+                       continue;
+               if (!(dep->flags & DWC3_EP_ENABLED))
+                       continue;
+               if (usb_endpoint_xfer_bulk(dep->desc)
+                               || usb_endpoint_xfer_isoc(dep->desc))
+                       mult = 3;
+               /*
+                * REVISIT: the following assumes we will always have enough
+                * space available on the FIFO RAM for all possible use cases.
+                * Make sure that's true somehow and change FIFO allocation
+                * accordingly.
+                *
+                * If we have Bulk or Isochronous endpoints, we want
+                * them to be able to be very, very fast. So we're giving
+                * those endpoints a fifo_size which is enough for 3 full
+                * packets
+                */
+               tmp = mult * (dep->endpoint.maxpacket + mdwidth);
+               tmp += mdwidth;
+               fifo_size = DIV_ROUND_UP(tmp, mdwidth);
+               fifo_size |= (last_fifo_depth << 16);
+               dev_vdbg(dwc->dev, "%s: Fifo Addr %04x Size %d\n",
+                               dep->name, last_fifo_depth, fifo_size & 0xffff);
+               dwc3_writel(dwc->regs, DWC3_GTXFIFOSIZ(fifo_number),
+                               fifo_size);
+               last_fifo_depth += (fifo_size & 0xffff);
+       }
+       return 0;
+ }
 -void dwc3_map_buffer_to_dma(struct dwc3_request *req)
 -{
 -      struct dwc3                     *dwc = req->dep->dwc;
 -
 -      if (req->request.length == 0) {
 -              /* req->request.dma = dwc->setup_buf_addr; */
 -              return;
 -      }
 -
 -      if (req->request.num_sgs) {
 -              int     mapped;
 -
 -              mapped = dma_map_sg(dwc->dev, req->request.sg,
 -                              req->request.num_sgs,
 -                              req->direction ? DMA_TO_DEVICE
 -                              : DMA_FROM_DEVICE);
 -              if (mapped < 0) {
 -                      dev_err(dwc->dev, "failed to map SGs\n");
 -                      return;
 -              }
 -
 -              req->request.num_mapped_sgs = mapped;
 -              return;
 -      }
 -
 -      if (req->request.dma == DMA_ADDR_INVALID) {
 -              req->request.dma = dma_map_single(dwc->dev, req->request.buf,
 -                              req->request.length, req->direction
 -                              ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
 -              req->mapped = true;
 -      }
 -}
 -
 -void dwc3_unmap_buffer_from_dma(struct dwc3_request *req)
 -{
 -      struct dwc3                     *dwc = req->dep->dwc;
 -
 -      if (req->request.length == 0) {
 -              req->request.dma = DMA_ADDR_INVALID;
 -              return;
 -      }
 -
 -      if (req->request.num_mapped_sgs) {
 -              req->request.dma = DMA_ADDR_INVALID;
 -              dma_unmap_sg(dwc->dev, req->request.sg,
 -                              req->request.num_mapped_sgs,
 -                              req->direction ? DMA_TO_DEVICE
 -                              : DMA_FROM_DEVICE);
 -
 -              req->request.num_mapped_sgs = 0;
 -              return;
 -      }
 -
 -      if (req->mapped) {
 -              dma_unmap_single(dwc->dev, req->request.dma,
 -                              req->request.length, req->direction
 -                              ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
 -              req->mapped = 0;
 -              req->request.dma = DMA_ADDR_INVALID;
 -      }
 -}
 -
  void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req,
                int status)
  {
@@@ -756,10 -984,9 +921,10 @@@ static int __dwc3_gadget_kick_transfer(
                /*
                 * FIXME we need to iterate over the list of requests
                 * here and stop, unmap, free and del each of the linked
-                * requests instead of we do now.
+                * requests instead of what we do now.
                 */
 -              dwc3_unmap_buffer_from_dma(req);
 +              usb_gadget_unmap_request(&dwc->gadget, &req->request,
 +                              req->direction);
                list_del(&req->list);
                return ret;
        }
@@@ -793,13 -1017,9 +958,13 @@@ static int __dwc3_gadget_ep_queue(struc
         * particular token from the Host side.
         *
         * This will also avoid Host cancelling URBs due to too
-        * many NACKs.
+        * many NAKs.
         */
 -      dwc3_map_buffer_to_dma(req);
 +      ret = usb_gadget_map_request(&dwc->gadget, &req->request,
 +                      dep->direction);
 +      if (ret)
 +              return ret;
 +
        list_add_tail(&req->list, &dep->request_list);
  
        /*
Simple merge