summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorPavan Kunapuli <pkunapuli@nvidia.com>2010-05-04 16:45:22 +0530
committerGary King <gking@nvidia.com>2010-05-07 16:44:18 -0700
commitc7707ab96e0ed9f7b841635d739ac16633ffd1a7 (patch)
tree500333c3659d69e204557d9f60b7ae1861b0614a /drivers
parent2293a1f7ac9ac8aca9180c5f245bca7cc95b6dea (diff)
udc/tegra: configure memory prefetcher for USB
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. Bug 597487 Change-Id: Iaf15a2bfb10cfc24d34bcb4b3093c1c6c48d5d22 Reviewed-on: http://git-master/r/1149 Reviewed-by: Gary King <gking@nvidia.com> Reviewed-by: Pavan Kunapuli <pkunapuli@nvidia.com> Tested-by: Pavan Kunapuli <pkunapuli@nvidia.com>
Diffstat (limited to 'drivers')
-rwxr-xr-xdrivers/usb/gadget/fsl_udc_core.c4
-rwxr-xr-xdrivers/usb/gadget/fsl_usb2_udc.h15
-rwxr-xr-xdrivers/usb/gadget/tegra_udc.c15
3 files changed, 34 insertions, 0 deletions
diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c
index 7f4149747b1a..c34350523437 100755
--- a/drivers/usb/gadget/fsl_udc_core.c
+++ b/drivers/usb/gadget/fsl_udc_core.c
@@ -719,6 +719,8 @@ static void fsl_queue_td(struct fsl_ep *ep, struct fsl_req *req)
/* Ensure that updates to the QH will occure before priming. */
wmb();
+ platform_udc_ep_barrier();
+
/* Prime endpoint by writing 1 to ENDPTPRIME */
temp = ep_is_in(ep)
? (1 << (ep_index(ep) + 16))
@@ -802,6 +804,8 @@ static int fsl_req_to_dtd(struct fsl_req *req)
struct ep_td_struct *last_dtd = NULL, *dtd;
dma_addr_t dma;
+ platform_udc_dtd_prepare();
+
do {
dtd = fsl_build_dtd(req, &count, &dma, &is_last);
if (dtd == NULL)
diff --git a/drivers/usb/gadget/fsl_usb2_udc.h b/drivers/usb/gadget/fsl_usb2_udc.h
index 5cdd6e983c8c..5594069d4d60 100755
--- a/drivers/usb/gadget/fsl_usb2_udc.h
+++ b/drivers/usb/gadget/fsl_usb2_udc.h
@@ -625,6 +625,17 @@ extern void platform_udc_clk_release(void);
extern void platform_udc_clk_suspend(void);
extern void platform_udc_clk_resume(void);
extern bool platform_udc_charger_detection(void);
+
+#ifdef CONFIG_ARCH_TEGRA
+#define platform_udc_dtd_prepare __glue(_UDC_NAME,_udc_dtd_prepare)
+#define platform_udc_ep_barrier __glue(_UDC_NAME,_udc_ep_barrier)
+extern void platform_udc_dtd_prepare(void);
+extern void platform_udc_ep_barrier(void);
+#else
+static inline void platform_udc_dtd_prepare(void) { }
+static inline void platform_udc_ep_barrier(void) { }
+#endif
+
#else
static inline int platform_udc_clk_init(struct platform_device *pdev)
{
@@ -638,6 +649,10 @@ static inline bool platform_udc_charger_detection(void)
{
return 0;
}
+static inline void platform_udc_dtd_prepare(void)
+{ }
+static inline void platform_udc_ep_barrier(void)
+{ }
#endif
#endif
diff --git a/drivers/usb/gadget/tegra_udc.c b/drivers/usb/gadget/tegra_udc.c
index a455a85741cb..413bcf58ab3a 100755
--- a/drivers/usb/gadget/tegra_udc.c
+++ b/drivers/usb/gadget/tegra_udc.c
@@ -92,3 +92,18 @@ bool tegra_udc_charger_detection(void)
return Status.ChargerDetected;
}
+
+void tegra_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.
+ */
+ NvDdkUsbPhyMemoryPrefetch(s_hUsbPhy, NV_FALSE);
+}
+
+void tegra_udc_ep_barrier(void)
+{
+ NvDdkUsbPhyMemoryPrefetch(s_hUsbPhy, NV_TRUE);
+}