diff options
author | Pavan Kunapuli <pkunapuli@nvidia.com> | 2010-05-04 16:45:22 +0530 |
---|---|---|
committer | Gary King <gking@nvidia.com> | 2010-05-07 16:44:18 -0700 |
commit | c7707ab96e0ed9f7b841635d739ac16633ffd1a7 (patch) | |
tree | 500333c3659d69e204557d9f60b7ae1861b0614a /drivers | |
parent | 2293a1f7ac9ac8aca9180c5f245bca7cc95b6dea (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-x | drivers/usb/gadget/fsl_udc_core.c | 4 | ||||
-rwxr-xr-x | drivers/usb/gadget/fsl_usb2_udc.h | 15 | ||||
-rwxr-xr-x | drivers/usb/gadget/tegra_udc.c | 15 |
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); +} |