diff options
author | Hemant Kumar <hemantk@codeaurora.org> | 2015-08-27 14:49:21 -0700 |
---|---|---|
committer | Jeevan Shriram <jshriram@codeaurora.org> | 2016-04-22 15:03:29 -0700 |
commit | b279a34274f95aef623b75aa18de939e15c66006 (patch) | |
tree | 746e98fc6b563973a095df2d6da9c05b0cae5280 /drivers/usb | |
parent | 6a4f3ec86c9e205575d57a4c3132c31433a921c6 (diff) |
usb: dwc3: Add support for GSI event buffer configuration
Add additional event buffers for GSI based hardware accelerated
endpoints and its related configuration.
CRs-Fixed: 1003784
Change-Id: Ibedf73690040b8bd872f5621835680a66c22e265
Signed-off-by: Hemant Kumar <hemantk@codeaurora.org>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/dwc3/core.c | 65 | ||||
-rw-r--r-- | drivers/usb/dwc3/core.h | 15 | ||||
-rw-r--r-- | drivers/usb/dwc3/gadget.c | 4 |
3 files changed, 69 insertions, 15 deletions
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index deef432bfd16..4fa506963ca1 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -247,7 +247,7 @@ static void dwc3_free_one_event_buffer(struct dwc3 *dwc, * otherwise ERR_PTR(errno). */ static struct dwc3_event_buffer *dwc3_alloc_one_event_buffer(struct dwc3 *dwc, - unsigned length) + unsigned length, enum event_buf_type type) { struct dwc3_event_buffer *evt; @@ -257,6 +257,7 @@ static struct dwc3_event_buffer *dwc3_alloc_one_event_buffer(struct dwc3 *dwc, evt->dwc = dwc; evt->length = length; + evt->type = type; evt->buf = dma_alloc_coherent(dwc->dev, length, &evt->dma, GFP_KERNEL); if (!evt->buf) @@ -291,26 +292,40 @@ static void dwc3_free_event_buffers(struct dwc3 *dwc) */ static int dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length) { - int num; - int i; + int i; + int j = 0; - num = DWC3_NUM_INT(dwc->hwparams.hwparams1); - dwc->num_event_buffers = num; + dwc->num_event_buffers = dwc->num_normal_event_buffers + + dwc->num_gsi_event_buffers; - dwc->ev_buffs = devm_kzalloc(dwc->dev, sizeof(*dwc->ev_buffs) * num, + dwc->ev_buffs = devm_kzalloc(dwc->dev, + sizeof(*dwc->ev_buffs) * dwc->num_event_buffers, GFP_KERNEL); if (!dwc->ev_buffs) return -ENOMEM; - for (i = 0; i < num; i++) { + for (i = 0; i < dwc->num_normal_event_buffers; i++) { struct dwc3_event_buffer *evt; - evt = dwc3_alloc_one_event_buffer(dwc, length); + evt = dwc3_alloc_one_event_buffer(dwc, length, + EVT_BUF_TYPE_NORMAL); if (IS_ERR(evt)) { dev_err(dwc->dev, "can't allocate event buffer\n"); return PTR_ERR(evt); } - dwc->ev_buffs[i] = evt; + dwc->ev_buffs[j++] = evt; + } + + for (i = 0; i < dwc->num_gsi_event_buffers; i++) { + struct dwc3_event_buffer *evt; + + evt = dwc3_alloc_one_event_buffer(dwc, length, + EVT_BUF_TYPE_GSI); + if (IS_ERR(evt)) { + dev_err(dwc->dev, "can't allocate event buffer\n"); + return PTR_ERR(evt); + } + dwc->ev_buffs[j++] = evt; } return 0; @@ -339,10 +354,23 @@ int dwc3_event_buffers_setup(struct dwc3 *dwc) dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n), lower_32_bits(evt->dma)); - dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n), - upper_32_bits(evt->dma)); - dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), - DWC3_GEVNTSIZ_SIZE(evt->length)); + + if (evt->type == EVT_BUF_TYPE_NORMAL) { + dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n), + upper_32_bits(evt->dma)); + dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), + DWC3_GEVNTSIZ_SIZE(evt->length)); + } else { + dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n), + DWC3_GEVNTADRHI_EVNTADRHI_GSI_EN( + DWC3_GEVENT_TYPE_GSI) | + DWC3_GEVNTADRHI_EVNTADRHI_GSI_IDX(n)); + + dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), + DWC3_GEVNTCOUNT_EVNTINTRPTMASK | + ((evt->length) & 0xffff)); + } + dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0); } @@ -962,6 +990,7 @@ static int dwc3_probe(struct platform_device *pdev) u8 tx_de_emphasis; u8 hird_threshold; u32 fladj = 0; + u32 num_evt_buffs; int ret; @@ -1084,6 +1113,16 @@ static int dwc3_probe(struct platform_device *pdev) "snps,disable-clk-gating"); dwc->enable_bus_suspend = device_property_read_bool(dev, "snps,bus-suspend-enable"); + + dwc->num_normal_event_buffers = 1; + ret = device_property_read_u32(dev, + "snps,num-normal-evt-buffs", &num_evt_buffs); + if (!ret) + dwc->num_normal_event_buffers = num_evt_buffs; + + ret = device_property_read_u32(dev, + "snps,num-gsi-evt-buffs", &dwc->num_gsi_event_buffers); + if (dwc->enable_bus_suspend) { pm_runtime_set_autosuspend_delay(dev, 500); pm_runtime_use_autosuspend(dev); diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 5fd15ebdc0e4..fa2a9d9a293a 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -128,6 +128,11 @@ #define DWC3_GEVNTSIZ(n) (0xc408 + (n * 0x10)) #define DWC3_GEVNTCOUNT(n) (0xc40c + (n * 0x10)) +#define DWC3_GEVNTCOUNT_EVNTINTRPTMASK (1 << 31) +#define DWC3_GEVNTADRHI_EVNTADRHI_GSI_EN(n) (n << 22) +#define DWC3_GEVNTADRHI_EVNTADRHI_GSI_IDX(n) (n << 16) +#define DWC3_GEVENT_TYPE_GSI 0x3 + #define DWC3_GHWPARAMS8 0xc600 #define DWC3_GFLADJ 0xc630 @@ -431,6 +436,11 @@ struct dwc3_trb; +enum event_buf_type { + EVT_BUF_TYPE_NORMAL, + EVT_BUF_TYPE_GSI +}; + /** * struct dwc3_event_buffer - Software event buffer representation * @buf: _THE_ buffer @@ -444,6 +454,7 @@ struct dwc3_trb; struct dwc3_event_buffer { void *buf; unsigned length; + enum event_buf_type type; unsigned int lpos; unsigned int count; unsigned int flags; @@ -868,6 +879,10 @@ struct dwc3 { u32 nr_scratch; u32 num_event_buffers; + u32 num_normal_event_buffers; + u32 num_gsi_event_buffers; + + u32 u1; u32 u1u2; u32 maximum_speed; diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 448cbdf6fa40..f146b965b2c4 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -3338,7 +3338,7 @@ static irqreturn_t dwc3_thread_interrupt(int irq, void *_dwc) spin_lock_irqsave(&dwc->lock, flags); dwc->bh_handled_evt_cnt[dwc->bh_dbg_index] = 0; - for (i = 0; i < dwc->num_event_buffers; i++) + for (i = 0; i < dwc->num_normal_event_buffers; i++) ret |= dwc3_process_event_buf(dwc, i); spin_unlock_irqrestore(&dwc->lock, flags); @@ -3397,7 +3397,7 @@ static irqreturn_t dwc3_interrupt(int irq, void *_dwc) if (dwc->err_evt_seen) return IRQ_HANDLED; - for (i = 0; i < dwc->num_event_buffers; i++) { + for (i = 0; i < dwc->num_normal_event_buffers; i++) { irqreturn_t status; status = dwc3_check_event_buf(dwc, i); |