diff options
author | Krishna Yarlagadda <kyarlagadda@nvidia.com> | 2012-03-26 14:57:27 +0530 |
---|---|---|
committer | Simone Willett <swillett@nvidia.com> | 2012-04-03 10:43:03 -0700 |
commit | 628e0c56855a235ce2e5f1765805535148e43e10 (patch) | |
tree | 493beb56b506389490f2158033e9fd0f11c8516a /drivers/usb | |
parent | c8755ec1291055904a53c6431e0462c263663c79 (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.c | 15 | ||||
-rw-r--r-- | drivers/usb/gadget/fsl_udc_core.c | 15 | ||||
-rw-r--r-- | drivers/usb/gadget/fsl_usb2_udc.h | 8 |
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 |