summaryrefslogtreecommitdiff
path: root/drivers/usb
diff options
context:
space:
mode:
authorKrishna Yarlagadda <kyarlagadda@nvidia.com>2012-03-26 14:57:27 +0530
committerSimone Willett <swillett@nvidia.com>2012-04-03 10:43:03 -0700
commit628e0c56855a235ce2e5f1765805535148e43e10 (patch)
tree493beb56b506389490f2158033e9fd0f11c8516a /drivers/usb
parentc8755ec1291055904a53c6431e0462c263663c79 (diff)
usb: gadget: tegra: Enable AHB prefetch
Enable AHB prefetch and call dma_sync to avoid memory coherency issues Bug 921109 Signed-off-by: Krishna Yarlagadda <kyarlagadda@nvidia.com> Reviewed-on: http://git-master/r/92257 (cherry picked from commit e8fac4b6f3460928442d6c9dadec301ccf57fb0b) Change-Id: I2788e94d3609bfdd6d112f0b5386a653af15075e Reviewed-on: http://git-master/r/93819 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Krishna Yarlagadda <kyarlagadda@nvidia.com> Tested-by: Krishna Yarlagadda <kyarlagadda@nvidia.com> Reviewed-by: Venkat Moganty <vmoganty@nvidia.com>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/gadget/fsl_tegra_udc.c15
-rw-r--r--drivers/usb/gadget/fsl_udc_core.c15
-rw-r--r--drivers/usb/gadget/fsl_usb2_udc.h8
3 files changed, 38 insertions, 0 deletions
diff --git a/drivers/usb/gadget/fsl_tegra_udc.c b/drivers/usb/gadget/fsl_tegra_udc.c
index b254258726fa..31b476ad2279 100644
--- a/drivers/usb/gadget/fsl_tegra_udc.c
+++ b/drivers/usb/gadget/fsl_tegra_udc.c
@@ -153,3 +153,18 @@ bool fsl_udc_charger_detect(void)
{
return tegra_usb_phy_charger_detect(phy);
}
+
+void fsl_udc_dtd_prepare(void)
+{
+ /* When we are programming two DTDs very close to each other,
+ * the second DTD is being prefetched before it is actually written
+ * to DDR. To prevent this, we disable prefetcher before programming
+ * any new DTD and re-enable it before priming endpoint.
+ */
+ tegra_usb_phy_memory_prefetch_off(phy);
+}
+
+void fsl_udc_ep_barrier(void)
+{
+ tegra_usb_phy_memory_prefetch_on(phy);
+}
diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c
index a406e32645d8..7dfbc5e95c96 100644
--- a/drivers/usb/gadget/fsl_udc_core.c
+++ b/drivers/usb/gadget/fsl_udc_core.c
@@ -869,6 +869,10 @@ static void fsl_queue_td(struct fsl_ep *ep, struct fsl_req *req)
| EP_QUEUE_HEAD_STATUS_HALT));
dQH->size_ioc_int_sts &= temp;
+#if defined(CONFIG_ARCH_TEGRA)
+ fsl_udc_ep_barrier();
+#endif
+
/* Ensure that updates to the QH will occur before priming. */
wmb();
@@ -955,6 +959,10 @@ static int fsl_req_to_dtd(struct fsl_req *req, gfp_t gfp_flags)
struct ep_td_struct *last_dtd = NULL, *dtd;
dma_addr_t dma;
+#if defined(CONFIG_ARCH_TEGRA)
+ fsl_udc_dtd_prepare();
+#endif
+
do {
dtd = fsl_build_dtd(req, &count, &dma, &is_last, gfp_flags);
if (dtd == NULL)
@@ -1964,6 +1972,13 @@ static int process_ep_req(struct fsl_udc *udc, int pipe,
actual = curr_req->req.length;
for (j = 0; j < curr_req->dtd_count; j++) {
+#ifdef CONFIG_ARCH_TEGRA
+ /* Fence read for coherency of AHB master intiated writes */
+ readb(IO_ADDRESS(IO_PPCS_PHYS + USB1_PREFETCH_ID));
+#endif
+ dma_sync_single_for_cpu(udc->gadget.dev.parent, curr_td->td_dma,
+ sizeof(struct ep_td_struct), DMA_FROM_DEVICE);
+
remaining_length = (hc32_to_cpu(curr_td->size_ioc_sts)
& DTD_PACKET_SIZE)
>> DTD_LENGTH_BIT_POS;
diff --git a/drivers/usb/gadget/fsl_usb2_udc.h b/drivers/usb/gadget/fsl_usb2_udc.h
index 62b26ed8c056..922092f1afdd 100644
--- a/drivers/usb/gadget/fsl_usb2_udc.h
+++ b/drivers/usb/gadget/fsl_usb2_udc.h
@@ -725,6 +725,8 @@ void fsl_udc_clk_resume(bool is_dpd);
void fsl_udc_clk_enable(void);
void fsl_udc_clk_disable(void);
bool fsl_udc_charger_detect(void);
+void fsl_udc_dtd_prepare(void);
+void fsl_udc_ep_barrier(void);
#else
static inline int fsl_udc_clk_init(struct platform_device *pdev)
{
@@ -752,6 +754,12 @@ static inline bool fsl_udc_charger_detect(void)
{
return false;
}
+void fsl_udc_dtd_prepare(void)
+{
+}
+void fsl_udc_ep_barrier(void)
+{
+}
#endif
#endif