diff options
Diffstat (limited to 'drivers/usb/musb/blackfin.c')
-rw-r--r-- | drivers/usb/musb/blackfin.c | 134 |
1 files changed, 91 insertions, 43 deletions
diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c index fe4934d9602c..ad26e6569665 100644 --- a/drivers/usb/musb/blackfin.c +++ b/drivers/usb/musb/blackfin.c | |||
@@ -29,6 +29,8 @@ void musb_write_fifo(struct musb_hw_ep *hw_ep, u16 len, const u8 *src) | |||
29 | { | 29 | { |
30 | void __iomem *fifo = hw_ep->fifo; | 30 | void __iomem *fifo = hw_ep->fifo; |
31 | void __iomem *epio = hw_ep->regs; | 31 | void __iomem *epio = hw_ep->regs; |
32 | u8 epnum = hw_ep->epnum; | ||
33 | u16 dma_reg = 0; | ||
32 | 34 | ||
33 | prefetch((u8 *)src); | 35 | prefetch((u8 *)src); |
34 | 36 | ||
@@ -39,67 +41,113 @@ void musb_write_fifo(struct musb_hw_ep *hw_ep, u16 len, const u8 *src) | |||
39 | 41 | ||
40 | dump_fifo_data(src, len); | 42 | dump_fifo_data(src, len); |
41 | 43 | ||
42 | if (unlikely((unsigned long)src & 0x01)) | 44 | if (!ANOMALY_05000380 && epnum != 0) { |
43 | outsw_8((unsigned long)fifo, src, | 45 | flush_dcache_range((unsigned int)src, |
44 | len & 0x01 ? (len >> 1) + 1 : len >> 1); | 46 | (unsigned int)(src + len)); |
45 | else | 47 | |
46 | outsw((unsigned long)fifo, src, | 48 | /* Setup DMA address register */ |
47 | len & 0x01 ? (len >> 1) + 1 : len >> 1); | 49 | dma_reg = (u16) ((u32) src & 0xFFFF); |
48 | } | 50 | bfin_write16(USB_DMA_REG(epnum, USB_DMAx_ADDR_LOW), dma_reg); |
51 | SSYNC(); | ||
52 | |||
53 | dma_reg = (u16) (((u32) src >> 16) & 0xFFFF); | ||
54 | bfin_write16(USB_DMA_REG(epnum, USB_DMAx_ADDR_HIGH), dma_reg); | ||
55 | SSYNC(); | ||
56 | |||
57 | /* Setup DMA count register */ | ||
58 | bfin_write16(USB_DMA_REG(epnum, USB_DMAx_COUNT_LOW), len); | ||
59 | bfin_write16(USB_DMA_REG(epnum, USB_DMAx_COUNT_HIGH), 0); | ||
60 | SSYNC(); | ||
61 | |||
62 | /* Enable the DMA */ | ||
63 | dma_reg = (epnum << 4) | DMA_ENA | INT_ENA | DIRECTION; | ||
64 | bfin_write16(USB_DMA_REG(epnum, USB_DMAx_CTRL), dma_reg); | ||
65 | SSYNC(); | ||
66 | |||
67 | /* Wait for compelete */ | ||
68 | while (!(bfin_read_USB_DMA_INTERRUPT() & (1 << epnum))) | ||
69 | cpu_relax(); | ||
70 | |||
71 | /* acknowledge dma interrupt */ | ||
72 | bfin_write_USB_DMA_INTERRUPT(1 << epnum); | ||
73 | SSYNC(); | ||
74 | |||
75 | /* Reset DMA */ | ||
76 | bfin_write16(USB_DMA_REG(epnum, USB_DMAx_CTRL), 0); | ||
77 | SSYNC(); | ||
78 | } else { | ||
79 | SSYNC(); | ||
80 | |||
81 | if (unlikely((unsigned long)src & 0x01)) | ||
82 | outsw_8((unsigned long)fifo, src, | ||
83 | len & 0x01 ? (len >> 1) + 1 : len >> 1); | ||
84 | else | ||
85 | outsw((unsigned long)fifo, src, | ||
86 | len & 0x01 ? (len >> 1) + 1 : len >> 1); | ||
49 | 87 | ||
88 | } | ||
89 | } | ||
50 | /* | 90 | /* |
51 | * Unload an endpoint's FIFO | 91 | * Unload an endpoint's FIFO |
52 | */ | 92 | */ |
53 | void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *dst) | 93 | void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *dst) |
54 | { | 94 | { |
55 | void __iomem *fifo = hw_ep->fifo; | 95 | void __iomem *fifo = hw_ep->fifo; |
56 | |||
57 | #ifdef CONFIG_BF52x | ||
58 | u8 epnum = hw_ep->epnum; | 96 | u8 epnum = hw_ep->epnum; |
59 | u16 dma_reg = 0; | 97 | u16 dma_reg = 0; |
60 | 98 | ||
61 | invalidate_dcache_range((unsigned int)dst, | 99 | if (ANOMALY_05000467 && epnum != 0) { |
62 | (unsigned int)(dst + len)); | ||
63 | 100 | ||
64 | /* Setup DMA address register */ | 101 | invalidate_dcache_range((unsigned int)dst, |
65 | dma_reg = (u16) ((u32) dst & 0xFFFF); | 102 | (unsigned int)(dst + len)); |
66 | bfin_write16(USB_DMA_REG(epnum, USB_DMAx_ADDR_LOW), dma_reg); | ||
67 | SSYNC(); | ||
68 | 103 | ||
69 | dma_reg = (u16) (((u32) dst >> 16) & 0xFFFF); | 104 | /* Setup DMA address register */ |
70 | bfin_write16(USB_DMA_REG(epnum, USB_DMAx_ADDR_HIGH), dma_reg); | 105 | dma_reg = (u16) ((u32) dst & 0xFFFF); |
71 | SSYNC(); | 106 | bfin_write16(USB_DMA_REG(epnum, USB_DMAx_ADDR_LOW), dma_reg); |
107 | SSYNC(); | ||
72 | 108 | ||
73 | /* Setup DMA count register */ | 109 | dma_reg = (u16) (((u32) dst >> 16) & 0xFFFF); |
74 | bfin_write16(USB_DMA_REG(epnum, USB_DMAx_COUNT_LOW), len); | 110 | bfin_write16(USB_DMA_REG(epnum, USB_DMAx_ADDR_HIGH), dma_reg); |
75 | bfin_write16(USB_DMA_REG(epnum, USB_DMAx_COUNT_HIGH), 0); | 111 | SSYNC(); |
76 | SSYNC(); | ||
77 | 112 | ||
78 | /* Enable the DMA */ | 113 | /* Setup DMA count register */ |
79 | dma_reg = (epnum << 4) | DMA_ENA | INT_ENA; | 114 | bfin_write16(USB_DMA_REG(epnum, USB_DMAx_COUNT_LOW), len); |
80 | bfin_write16(USB_DMA_REG(epnum, USB_DMAx_CTRL), dma_reg); | 115 | bfin_write16(USB_DMA_REG(epnum, USB_DMAx_COUNT_HIGH), 0); |
81 | SSYNC(); | 116 | SSYNC(); |
82 | 117 | ||
83 | /* Wait for compelete */ | 118 | /* Enable the DMA */ |
84 | while (!(bfin_read_USB_DMA_INTERRUPT() & (1 << epnum))) | 119 | dma_reg = (epnum << 4) | DMA_ENA | INT_ENA; |
85 | cpu_relax(); | 120 | bfin_write16(USB_DMA_REG(epnum, USB_DMAx_CTRL), dma_reg); |
121 | SSYNC(); | ||
86 | 122 | ||
87 | /* acknowledge dma interrupt */ | 123 | /* Wait for compelete */ |
88 | bfin_write_USB_DMA_INTERRUPT(1 << epnum); | 124 | while (!(bfin_read_USB_DMA_INTERRUPT() & (1 << epnum))) |
89 | SSYNC(); | 125 | cpu_relax(); |
90 | 126 | ||
91 | /* Reset DMA */ | 127 | /* acknowledge dma interrupt */ |
92 | bfin_write16(USB_DMA_REG(epnum, USB_DMAx_CTRL), 0); | 128 | bfin_write_USB_DMA_INTERRUPT(1 << epnum); |
93 | SSYNC(); | 129 | SSYNC(); |
94 | #else | ||
95 | if (unlikely((unsigned long)dst & 0x01)) | ||
96 | insw_8((unsigned long)fifo, dst, | ||
97 | len & 0x01 ? (len >> 1) + 1 : len >> 1); | ||
98 | else | ||
99 | insw((unsigned long)fifo, dst, | ||
100 | len & 0x01 ? (len >> 1) + 1 : len >> 1); | ||
101 | #endif | ||
102 | 130 | ||
131 | /* Reset DMA */ | ||
132 | bfin_write16(USB_DMA_REG(epnum, USB_DMAx_CTRL), 0); | ||
133 | SSYNC(); | ||
134 | } else { | ||
135 | SSYNC(); | ||
136 | /* Read the last byte of packet with odd size from address fifo + 4 | ||
137 | * to trigger 1 byte access to EP0 FIFO. | ||
138 | */ | ||
139 | if (len == 1) | ||
140 | *dst = (u8)inw((unsigned long)fifo + 4); | ||
141 | else { | ||
142 | if (unlikely((unsigned long)dst & 0x01)) | ||
143 | insw_8((unsigned long)fifo, dst, len >> 1); | ||
144 | else | ||
145 | insw((unsigned long)fifo, dst, len >> 1); | ||
146 | |||
147 | if (len & 0x01) | ||
148 | *(dst + len - 1) = (u8)inw((unsigned long)fifo + 4); | ||
149 | } | ||
150 | } | ||
103 | DBG(4, "%cX ep%d fifo %p count %d buf %p\n", | 151 | DBG(4, "%cX ep%d fifo %p count %d buf %p\n", |
104 | 'R', hw_ep->epnum, fifo, len, dst); | 152 | 'R', hw_ep->epnum, fifo, len, dst); |
105 | 153 | ||