summaryrefslogtreecommitdiff
path: root/drivers/usb
diff options
context:
space:
mode:
authorHemant Kumar <hemantk@codeaurora.org>2015-08-27 14:49:21 -0700
committerJeevan Shriram <jshriram@codeaurora.org>2016-04-22 15:03:29 -0700
commitb279a34274f95aef623b75aa18de939e15c66006 (patch)
tree746e98fc6b563973a095df2d6da9c05b0cae5280 /drivers/usb
parent6a4f3ec86c9e205575d57a4c3132c31433a921c6 (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.c65
-rw-r--r--drivers/usb/dwc3/core.h15
-rw-r--r--drivers/usb/dwc3/gadget.c4
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);