Commit 9e74d601de8adb0fe96e100e459ac52f2ddd47f3
Committed by
Felipe Balbi
1 parent
89c1d2e7b5
Exists in
master
and in
6 other branches
usb: gadget: renesas_usbhs: add data/status stage handler
mod_host needs data/status stage handler Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Signed-off-by: Felipe Balbi <balbi@ti.com>
Showing 2 changed files with 150 additions and 0 deletions Inline Diff
drivers/usb/renesas_usbhs/fifo.c
1 | /* | 1 | /* |
2 | * Renesas USB driver | 2 | * Renesas USB driver |
3 | * | 3 | * |
4 | * Copyright (C) 2011 Renesas Solutions Corp. | 4 | * Copyright (C) 2011 Renesas Solutions Corp. |
5 | * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | 5 | * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> |
6 | * | 6 | * |
7 | * This program is distributed in the hope that it will be useful, | 7 | * This program is distributed in the hope that it will be useful, |
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
10 | * GNU General Public License for more details. | 10 | * GNU General Public License for more details. |
11 | * | 11 | * |
12 | * You should have received a copy of the GNU General Public License | 12 | * You should have received a copy of the GNU General Public License |
13 | * along with this program; if not, write to the Free Software | 13 | * along with this program; if not, write to the Free Software |
14 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 14 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
15 | * | 15 | * |
16 | */ | 16 | */ |
17 | #include <linux/delay.h> | 17 | #include <linux/delay.h> |
18 | #include <linux/io.h> | 18 | #include <linux/io.h> |
19 | #include <linux/scatterlist.h> | 19 | #include <linux/scatterlist.h> |
20 | #include "./common.h" | 20 | #include "./common.h" |
21 | #include "./pipe.h" | 21 | #include "./pipe.h" |
22 | 22 | ||
23 | #define usbhsf_get_cfifo(p) (&((p)->fifo_info.cfifo)) | 23 | #define usbhsf_get_cfifo(p) (&((p)->fifo_info.cfifo)) |
24 | #define usbhsf_get_d0fifo(p) (&((p)->fifo_info.d0fifo)) | 24 | #define usbhsf_get_d0fifo(p) (&((p)->fifo_info.d0fifo)) |
25 | #define usbhsf_get_d1fifo(p) (&((p)->fifo_info.d1fifo)) | 25 | #define usbhsf_get_d1fifo(p) (&((p)->fifo_info.d1fifo)) |
26 | 26 | ||
27 | #define usbhsf_fifo_is_busy(f) ((f)->pipe) /* see usbhs_pipe_select_fifo */ | 27 | #define usbhsf_fifo_is_busy(f) ((f)->pipe) /* see usbhs_pipe_select_fifo */ |
28 | 28 | ||
29 | /* | 29 | /* |
30 | * packet initialize | 30 | * packet initialize |
31 | */ | 31 | */ |
32 | void usbhs_pkt_init(struct usbhs_pkt *pkt) | 32 | void usbhs_pkt_init(struct usbhs_pkt *pkt) |
33 | { | 33 | { |
34 | pkt->dma = DMA_ADDR_INVALID; | 34 | pkt->dma = DMA_ADDR_INVALID; |
35 | INIT_LIST_HEAD(&pkt->node); | 35 | INIT_LIST_HEAD(&pkt->node); |
36 | } | 36 | } |
37 | 37 | ||
38 | /* | 38 | /* |
39 | * packet control function | 39 | * packet control function |
40 | */ | 40 | */ |
41 | static int usbhsf_null_handle(struct usbhs_pkt *pkt, int *is_done) | 41 | static int usbhsf_null_handle(struct usbhs_pkt *pkt, int *is_done) |
42 | { | 42 | { |
43 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pkt->pipe); | 43 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pkt->pipe); |
44 | struct device *dev = usbhs_priv_to_dev(priv); | 44 | struct device *dev = usbhs_priv_to_dev(priv); |
45 | 45 | ||
46 | dev_err(dev, "null handler\n"); | 46 | dev_err(dev, "null handler\n"); |
47 | 47 | ||
48 | return -EINVAL; | 48 | return -EINVAL; |
49 | } | 49 | } |
50 | 50 | ||
51 | static struct usbhs_pkt_handle usbhsf_null_handler = { | 51 | static struct usbhs_pkt_handle usbhsf_null_handler = { |
52 | .prepare = usbhsf_null_handle, | 52 | .prepare = usbhsf_null_handle, |
53 | .try_run = usbhsf_null_handle, | 53 | .try_run = usbhsf_null_handle, |
54 | }; | 54 | }; |
55 | 55 | ||
56 | void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt, | 56 | void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt, |
57 | void (*done)(struct usbhs_priv *priv, | 57 | void (*done)(struct usbhs_priv *priv, |
58 | struct usbhs_pkt *pkt), | 58 | struct usbhs_pkt *pkt), |
59 | void *buf, int len, int zero) | 59 | void *buf, int len, int zero) |
60 | { | 60 | { |
61 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | 61 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); |
62 | struct device *dev = usbhs_priv_to_dev(priv); | 62 | struct device *dev = usbhs_priv_to_dev(priv); |
63 | unsigned long flags; | 63 | unsigned long flags; |
64 | 64 | ||
65 | /******************** spin lock ********************/ | 65 | /******************** spin lock ********************/ |
66 | usbhs_lock(priv, flags); | 66 | usbhs_lock(priv, flags); |
67 | 67 | ||
68 | if (!done) { | 68 | if (!done) { |
69 | dev_err(dev, "no done function\n"); | 69 | dev_err(dev, "no done function\n"); |
70 | return; | 70 | return; |
71 | } | 71 | } |
72 | 72 | ||
73 | if (!pipe->handler) { | 73 | if (!pipe->handler) { |
74 | dev_err(dev, "no handler function\n"); | 74 | dev_err(dev, "no handler function\n"); |
75 | pipe->handler = &usbhsf_null_handler; | 75 | pipe->handler = &usbhsf_null_handler; |
76 | } | 76 | } |
77 | 77 | ||
78 | list_del_init(&pkt->node); | 78 | list_del_init(&pkt->node); |
79 | list_add_tail(&pkt->node, &pipe->list); | 79 | list_add_tail(&pkt->node, &pipe->list); |
80 | 80 | ||
81 | /* | 81 | /* |
82 | * each pkt must hold own handler. | 82 | * each pkt must hold own handler. |
83 | * because handler might be changed by its situation. | 83 | * because handler might be changed by its situation. |
84 | * dma handler -> pio handler. | 84 | * dma handler -> pio handler. |
85 | */ | 85 | */ |
86 | pkt->pipe = pipe; | 86 | pkt->pipe = pipe; |
87 | pkt->buf = buf; | 87 | pkt->buf = buf; |
88 | pkt->handler = pipe->handler; | 88 | pkt->handler = pipe->handler; |
89 | pkt->length = len; | 89 | pkt->length = len; |
90 | pkt->zero = zero; | 90 | pkt->zero = zero; |
91 | pkt->actual = 0; | 91 | pkt->actual = 0; |
92 | pkt->done = done; | 92 | pkt->done = done; |
93 | 93 | ||
94 | usbhs_unlock(priv, flags); | 94 | usbhs_unlock(priv, flags); |
95 | /******************** spin unlock ******************/ | 95 | /******************** spin unlock ******************/ |
96 | } | 96 | } |
97 | 97 | ||
98 | static void __usbhsf_pkt_del(struct usbhs_pkt *pkt) | 98 | static void __usbhsf_pkt_del(struct usbhs_pkt *pkt) |
99 | { | 99 | { |
100 | list_del_init(&pkt->node); | 100 | list_del_init(&pkt->node); |
101 | } | 101 | } |
102 | 102 | ||
103 | static struct usbhs_pkt *__usbhsf_pkt_get(struct usbhs_pipe *pipe) | 103 | static struct usbhs_pkt *__usbhsf_pkt_get(struct usbhs_pipe *pipe) |
104 | { | 104 | { |
105 | if (list_empty(&pipe->list)) | 105 | if (list_empty(&pipe->list)) |
106 | return NULL; | 106 | return NULL; |
107 | 107 | ||
108 | return list_entry(pipe->list.next, struct usbhs_pkt, node); | 108 | return list_entry(pipe->list.next, struct usbhs_pkt, node); |
109 | } | 109 | } |
110 | 110 | ||
111 | struct usbhs_pkt *usbhs_pkt_pop(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt) | 111 | struct usbhs_pkt *usbhs_pkt_pop(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt) |
112 | { | 112 | { |
113 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | 113 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); |
114 | unsigned long flags; | 114 | unsigned long flags; |
115 | 115 | ||
116 | /******************** spin lock ********************/ | 116 | /******************** spin lock ********************/ |
117 | usbhs_lock(priv, flags); | 117 | usbhs_lock(priv, flags); |
118 | 118 | ||
119 | if (!pkt) | 119 | if (!pkt) |
120 | pkt = __usbhsf_pkt_get(pipe); | 120 | pkt = __usbhsf_pkt_get(pipe); |
121 | 121 | ||
122 | if (pkt) | 122 | if (pkt) |
123 | __usbhsf_pkt_del(pkt); | 123 | __usbhsf_pkt_del(pkt); |
124 | 124 | ||
125 | usbhs_unlock(priv, flags); | 125 | usbhs_unlock(priv, flags); |
126 | /******************** spin unlock ******************/ | 126 | /******************** spin unlock ******************/ |
127 | 127 | ||
128 | return pkt; | 128 | return pkt; |
129 | } | 129 | } |
130 | 130 | ||
131 | enum { | 131 | enum { |
132 | USBHSF_PKT_PREPARE, | 132 | USBHSF_PKT_PREPARE, |
133 | USBHSF_PKT_TRY_RUN, | 133 | USBHSF_PKT_TRY_RUN, |
134 | USBHSF_PKT_DMA_DONE, | 134 | USBHSF_PKT_DMA_DONE, |
135 | }; | 135 | }; |
136 | 136 | ||
137 | static int usbhsf_pkt_handler(struct usbhs_pipe *pipe, int type) | 137 | static int usbhsf_pkt_handler(struct usbhs_pipe *pipe, int type) |
138 | { | 138 | { |
139 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | 139 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); |
140 | struct usbhs_pkt *pkt; | 140 | struct usbhs_pkt *pkt; |
141 | struct device *dev = usbhs_priv_to_dev(priv); | 141 | struct device *dev = usbhs_priv_to_dev(priv); |
142 | int (*func)(struct usbhs_pkt *pkt, int *is_done); | 142 | int (*func)(struct usbhs_pkt *pkt, int *is_done); |
143 | unsigned long flags; | 143 | unsigned long flags; |
144 | int ret = 0; | 144 | int ret = 0; |
145 | int is_done = 0; | 145 | int is_done = 0; |
146 | 146 | ||
147 | /******************** spin lock ********************/ | 147 | /******************** spin lock ********************/ |
148 | usbhs_lock(priv, flags); | 148 | usbhs_lock(priv, flags); |
149 | 149 | ||
150 | pkt = __usbhsf_pkt_get(pipe); | 150 | pkt = __usbhsf_pkt_get(pipe); |
151 | if (!pkt) | 151 | if (!pkt) |
152 | goto __usbhs_pkt_handler_end; | 152 | goto __usbhs_pkt_handler_end; |
153 | 153 | ||
154 | switch (type) { | 154 | switch (type) { |
155 | case USBHSF_PKT_PREPARE: | 155 | case USBHSF_PKT_PREPARE: |
156 | func = pkt->handler->prepare; | 156 | func = pkt->handler->prepare; |
157 | break; | 157 | break; |
158 | case USBHSF_PKT_TRY_RUN: | 158 | case USBHSF_PKT_TRY_RUN: |
159 | func = pkt->handler->try_run; | 159 | func = pkt->handler->try_run; |
160 | break; | 160 | break; |
161 | case USBHSF_PKT_DMA_DONE: | 161 | case USBHSF_PKT_DMA_DONE: |
162 | func = pkt->handler->dma_done; | 162 | func = pkt->handler->dma_done; |
163 | break; | 163 | break; |
164 | default: | 164 | default: |
165 | dev_err(dev, "unknown pkt hander\n"); | 165 | dev_err(dev, "unknown pkt hander\n"); |
166 | goto __usbhs_pkt_handler_end; | 166 | goto __usbhs_pkt_handler_end; |
167 | } | 167 | } |
168 | 168 | ||
169 | ret = func(pkt, &is_done); | 169 | ret = func(pkt, &is_done); |
170 | 170 | ||
171 | if (is_done) | 171 | if (is_done) |
172 | __usbhsf_pkt_del(pkt); | 172 | __usbhsf_pkt_del(pkt); |
173 | 173 | ||
174 | __usbhs_pkt_handler_end: | 174 | __usbhs_pkt_handler_end: |
175 | usbhs_unlock(priv, flags); | 175 | usbhs_unlock(priv, flags); |
176 | /******************** spin unlock ******************/ | 176 | /******************** spin unlock ******************/ |
177 | 177 | ||
178 | if (is_done) { | 178 | if (is_done) { |
179 | pkt->done(priv, pkt); | 179 | pkt->done(priv, pkt); |
180 | usbhs_pkt_start(pipe); | 180 | usbhs_pkt_start(pipe); |
181 | } | 181 | } |
182 | 182 | ||
183 | return ret; | 183 | return ret; |
184 | } | 184 | } |
185 | 185 | ||
186 | void usbhs_pkt_start(struct usbhs_pipe *pipe) | 186 | void usbhs_pkt_start(struct usbhs_pipe *pipe) |
187 | { | 187 | { |
188 | usbhsf_pkt_handler(pipe, USBHSF_PKT_PREPARE); | 188 | usbhsf_pkt_handler(pipe, USBHSF_PKT_PREPARE); |
189 | } | 189 | } |
190 | 190 | ||
191 | /* | 191 | /* |
192 | * irq enable/disable function | 192 | * irq enable/disable function |
193 | */ | 193 | */ |
194 | #define usbhsf_irq_empty_ctrl(p, e) usbhsf_irq_callback_ctrl(p, bempsts, e) | 194 | #define usbhsf_irq_empty_ctrl(p, e) usbhsf_irq_callback_ctrl(p, bempsts, e) |
195 | #define usbhsf_irq_ready_ctrl(p, e) usbhsf_irq_callback_ctrl(p, brdysts, e) | 195 | #define usbhsf_irq_ready_ctrl(p, e) usbhsf_irq_callback_ctrl(p, brdysts, e) |
196 | #define usbhsf_irq_callback_ctrl(pipe, status, enable) \ | 196 | #define usbhsf_irq_callback_ctrl(pipe, status, enable) \ |
197 | ({ \ | 197 | ({ \ |
198 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); \ | 198 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); \ |
199 | struct usbhs_mod *mod = usbhs_mod_get_current(priv); \ | 199 | struct usbhs_mod *mod = usbhs_mod_get_current(priv); \ |
200 | u16 status = (1 << usbhs_pipe_number(pipe)); \ | 200 | u16 status = (1 << usbhs_pipe_number(pipe)); \ |
201 | if (!mod) \ | 201 | if (!mod) \ |
202 | return; \ | 202 | return; \ |
203 | if (enable) \ | 203 | if (enable) \ |
204 | mod->irq_##status |= status; \ | 204 | mod->irq_##status |= status; \ |
205 | else \ | 205 | else \ |
206 | mod->irq_##status &= ~status; \ | 206 | mod->irq_##status &= ~status; \ |
207 | usbhs_irq_callback_update(priv, mod); \ | 207 | usbhs_irq_callback_update(priv, mod); \ |
208 | }) | 208 | }) |
209 | 209 | ||
210 | static void usbhsf_tx_irq_ctrl(struct usbhs_pipe *pipe, int enable) | 210 | static void usbhsf_tx_irq_ctrl(struct usbhs_pipe *pipe, int enable) |
211 | { | 211 | { |
212 | /* | 212 | /* |
213 | * And DCP pipe can NOT use "ready interrupt" for "send" | 213 | * And DCP pipe can NOT use "ready interrupt" for "send" |
214 | * it should use "empty" interrupt. | 214 | * it should use "empty" interrupt. |
215 | * see | 215 | * see |
216 | * "Operation" - "Interrupt Function" - "BRDY Interrupt" | 216 | * "Operation" - "Interrupt Function" - "BRDY Interrupt" |
217 | * | 217 | * |
218 | * on the other hand, normal pipe can use "ready interrupt" for "send" | 218 | * on the other hand, normal pipe can use "ready interrupt" for "send" |
219 | * even though it is single/double buffer | 219 | * even though it is single/double buffer |
220 | */ | 220 | */ |
221 | if (usbhs_pipe_is_dcp(pipe)) | 221 | if (usbhs_pipe_is_dcp(pipe)) |
222 | usbhsf_irq_empty_ctrl(pipe, enable); | 222 | usbhsf_irq_empty_ctrl(pipe, enable); |
223 | else | 223 | else |
224 | usbhsf_irq_ready_ctrl(pipe, enable); | 224 | usbhsf_irq_ready_ctrl(pipe, enable); |
225 | } | 225 | } |
226 | 226 | ||
227 | static void usbhsf_rx_irq_ctrl(struct usbhs_pipe *pipe, int enable) | 227 | static void usbhsf_rx_irq_ctrl(struct usbhs_pipe *pipe, int enable) |
228 | { | 228 | { |
229 | usbhsf_irq_ready_ctrl(pipe, enable); | 229 | usbhsf_irq_ready_ctrl(pipe, enable); |
230 | } | 230 | } |
231 | 231 | ||
232 | /* | 232 | /* |
233 | * FIFO ctrl | 233 | * FIFO ctrl |
234 | */ | 234 | */ |
235 | static void usbhsf_send_terminator(struct usbhs_pipe *pipe, | 235 | static void usbhsf_send_terminator(struct usbhs_pipe *pipe, |
236 | struct usbhs_fifo *fifo) | 236 | struct usbhs_fifo *fifo) |
237 | { | 237 | { |
238 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | 238 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); |
239 | 239 | ||
240 | usbhs_bset(priv, fifo->ctr, BVAL, BVAL); | 240 | usbhs_bset(priv, fifo->ctr, BVAL, BVAL); |
241 | } | 241 | } |
242 | 242 | ||
243 | static int usbhsf_fifo_barrier(struct usbhs_priv *priv, | 243 | static int usbhsf_fifo_barrier(struct usbhs_priv *priv, |
244 | struct usbhs_fifo *fifo) | 244 | struct usbhs_fifo *fifo) |
245 | { | 245 | { |
246 | int timeout = 1024; | 246 | int timeout = 1024; |
247 | 247 | ||
248 | do { | 248 | do { |
249 | /* The FIFO port is accessible */ | 249 | /* The FIFO port is accessible */ |
250 | if (usbhs_read(priv, fifo->ctr) & FRDY) | 250 | if (usbhs_read(priv, fifo->ctr) & FRDY) |
251 | return 0; | 251 | return 0; |
252 | 252 | ||
253 | udelay(10); | 253 | udelay(10); |
254 | } while (timeout--); | 254 | } while (timeout--); |
255 | 255 | ||
256 | return -EBUSY; | 256 | return -EBUSY; |
257 | } | 257 | } |
258 | 258 | ||
259 | static void usbhsf_fifo_clear(struct usbhs_pipe *pipe, | 259 | static void usbhsf_fifo_clear(struct usbhs_pipe *pipe, |
260 | struct usbhs_fifo *fifo) | 260 | struct usbhs_fifo *fifo) |
261 | { | 261 | { |
262 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | 262 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); |
263 | 263 | ||
264 | if (!usbhs_pipe_is_dcp(pipe)) | 264 | if (!usbhs_pipe_is_dcp(pipe)) |
265 | usbhsf_fifo_barrier(priv, fifo); | 265 | usbhsf_fifo_barrier(priv, fifo); |
266 | 266 | ||
267 | usbhs_write(priv, fifo->ctr, BCLR); | 267 | usbhs_write(priv, fifo->ctr, BCLR); |
268 | } | 268 | } |
269 | 269 | ||
270 | static int usbhsf_fifo_rcv_len(struct usbhs_priv *priv, | 270 | static int usbhsf_fifo_rcv_len(struct usbhs_priv *priv, |
271 | struct usbhs_fifo *fifo) | 271 | struct usbhs_fifo *fifo) |
272 | { | 272 | { |
273 | return usbhs_read(priv, fifo->ctr) & DTLN_MASK; | 273 | return usbhs_read(priv, fifo->ctr) & DTLN_MASK; |
274 | } | 274 | } |
275 | 275 | ||
276 | static void usbhsf_fifo_unselect(struct usbhs_pipe *pipe, | 276 | static void usbhsf_fifo_unselect(struct usbhs_pipe *pipe, |
277 | struct usbhs_fifo *fifo) | 277 | struct usbhs_fifo *fifo) |
278 | { | 278 | { |
279 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | 279 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); |
280 | 280 | ||
281 | usbhs_pipe_select_fifo(pipe, NULL); | 281 | usbhs_pipe_select_fifo(pipe, NULL); |
282 | usbhs_write(priv, fifo->sel, 0); | 282 | usbhs_write(priv, fifo->sel, 0); |
283 | } | 283 | } |
284 | 284 | ||
285 | static int usbhsf_fifo_select(struct usbhs_pipe *pipe, | 285 | static int usbhsf_fifo_select(struct usbhs_pipe *pipe, |
286 | struct usbhs_fifo *fifo, | 286 | struct usbhs_fifo *fifo, |
287 | int write) | 287 | int write) |
288 | { | 288 | { |
289 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | 289 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); |
290 | struct device *dev = usbhs_priv_to_dev(priv); | 290 | struct device *dev = usbhs_priv_to_dev(priv); |
291 | int timeout = 1024; | 291 | int timeout = 1024; |
292 | u16 mask = ((1 << 5) | 0xF); /* mask of ISEL | CURPIPE */ | 292 | u16 mask = ((1 << 5) | 0xF); /* mask of ISEL | CURPIPE */ |
293 | u16 base = usbhs_pipe_number(pipe); /* CURPIPE */ | 293 | u16 base = usbhs_pipe_number(pipe); /* CURPIPE */ |
294 | 294 | ||
295 | if (usbhs_pipe_is_busy(pipe) || | 295 | if (usbhs_pipe_is_busy(pipe) || |
296 | usbhsf_fifo_is_busy(fifo)) | 296 | usbhsf_fifo_is_busy(fifo)) |
297 | return -EBUSY; | 297 | return -EBUSY; |
298 | 298 | ||
299 | if (usbhs_pipe_is_dcp(pipe)) { | 299 | if (usbhs_pipe_is_dcp(pipe)) { |
300 | base |= (1 == write) << 5; /* ISEL */ | 300 | base |= (1 == write) << 5; /* ISEL */ |
301 | 301 | ||
302 | if (usbhs_mod_is_host(priv)) | 302 | if (usbhs_mod_is_host(priv)) |
303 | usbhs_dcp_dir_for_host(pipe, write); | 303 | usbhs_dcp_dir_for_host(pipe, write); |
304 | } | 304 | } |
305 | 305 | ||
306 | /* "base" will be used below */ | 306 | /* "base" will be used below */ |
307 | usbhs_write(priv, fifo->sel, base | MBW_32); | 307 | usbhs_write(priv, fifo->sel, base | MBW_32); |
308 | 308 | ||
309 | /* check ISEL and CURPIPE value */ | 309 | /* check ISEL and CURPIPE value */ |
310 | while (timeout--) { | 310 | while (timeout--) { |
311 | if (base == (mask & usbhs_read(priv, fifo->sel))) { | 311 | if (base == (mask & usbhs_read(priv, fifo->sel))) { |
312 | usbhs_pipe_select_fifo(pipe, fifo); | 312 | usbhs_pipe_select_fifo(pipe, fifo); |
313 | return 0; | 313 | return 0; |
314 | } | 314 | } |
315 | udelay(10); | 315 | udelay(10); |
316 | } | 316 | } |
317 | 317 | ||
318 | dev_err(dev, "fifo select error\n"); | 318 | dev_err(dev, "fifo select error\n"); |
319 | 319 | ||
320 | return -EIO; | 320 | return -EIO; |
321 | } | 321 | } |
322 | 322 | ||
323 | /* | 323 | /* |
324 | * DCP status stage | ||
325 | */ | ||
326 | static int usbhs_dcp_dir_switch_to_write(struct usbhs_pkt *pkt, int *is_done) | ||
327 | { | ||
328 | struct usbhs_pipe *pipe = pkt->pipe; | ||
329 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | ||
330 | struct usbhs_fifo *fifo = usbhsf_get_cfifo(priv); /* CFIFO */ | ||
331 | struct device *dev = usbhs_priv_to_dev(priv); | ||
332 | int ret; | ||
333 | |||
334 | usbhs_pipe_disable(pipe); | ||
335 | |||
336 | ret = usbhsf_fifo_select(pipe, fifo, 1); | ||
337 | if (ret < 0) { | ||
338 | dev_err(dev, "%s() faile\n", __func__); | ||
339 | return ret; | ||
340 | } | ||
341 | |||
342 | usbhs_pipe_sequence_data1(pipe); /* DATA1 */ | ||
343 | |||
344 | usbhsf_fifo_clear(pipe, fifo); | ||
345 | usbhsf_send_terminator(pipe, fifo); | ||
346 | |||
347 | usbhsf_fifo_unselect(pipe, fifo); | ||
348 | |||
349 | usbhsf_tx_irq_ctrl(pipe, 1); | ||
350 | usbhs_pipe_enable(pipe); | ||
351 | |||
352 | return ret; | ||
353 | } | ||
354 | |||
355 | static int usbhs_dcp_dir_switch_to_read(struct usbhs_pkt *pkt, int *is_done) | ||
356 | { | ||
357 | struct usbhs_pipe *pipe = pkt->pipe; | ||
358 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | ||
359 | struct usbhs_fifo *fifo = usbhsf_get_cfifo(priv); /* CFIFO */ | ||
360 | struct device *dev = usbhs_priv_to_dev(priv); | ||
361 | int ret; | ||
362 | |||
363 | usbhs_pipe_disable(pipe); | ||
364 | |||
365 | ret = usbhsf_fifo_select(pipe, fifo, 0); | ||
366 | if (ret < 0) { | ||
367 | dev_err(dev, "%s() fail\n", __func__); | ||
368 | return ret; | ||
369 | } | ||
370 | |||
371 | usbhs_pipe_sequence_data1(pipe); /* DATA1 */ | ||
372 | usbhsf_fifo_clear(pipe, fifo); | ||
373 | |||
374 | usbhsf_fifo_unselect(pipe, fifo); | ||
375 | |||
376 | usbhsf_rx_irq_ctrl(pipe, 1); | ||
377 | usbhs_pipe_enable(pipe); | ||
378 | |||
379 | return ret; | ||
380 | |||
381 | } | ||
382 | |||
383 | static int usbhs_dcp_dir_switch_done(struct usbhs_pkt *pkt, int *is_done) | ||
384 | { | ||
385 | struct usbhs_pipe *pipe = pkt->pipe; | ||
386 | |||
387 | if (pkt->handler == &usbhs_dcp_status_stage_in_handler) | ||
388 | usbhsf_tx_irq_ctrl(pipe, 0); | ||
389 | else | ||
390 | usbhsf_rx_irq_ctrl(pipe, 0); | ||
391 | |||
392 | pkt->actual = pkt->length; | ||
393 | *is_done = 1; | ||
394 | |||
395 | return 0; | ||
396 | } | ||
397 | |||
398 | struct usbhs_pkt_handle usbhs_dcp_status_stage_in_handler = { | ||
399 | .prepare = usbhs_dcp_dir_switch_to_write, | ||
400 | .try_run = usbhs_dcp_dir_switch_done, | ||
401 | }; | ||
402 | |||
403 | struct usbhs_pkt_handle usbhs_dcp_status_stage_out_handler = { | ||
404 | .prepare = usbhs_dcp_dir_switch_to_read, | ||
405 | .try_run = usbhs_dcp_dir_switch_done, | ||
406 | }; | ||
407 | |||
408 | /* | ||
409 | * DCP data stage (push) | ||
410 | */ | ||
411 | static int usbhsf_dcp_data_stage_try_push(struct usbhs_pkt *pkt, int *is_done) | ||
412 | { | ||
413 | struct usbhs_pipe *pipe = pkt->pipe; | ||
414 | |||
415 | usbhs_pipe_sequence_data1(pipe); /* DATA1 */ | ||
416 | |||
417 | /* | ||
418 | * change handler to PIO push | ||
419 | */ | ||
420 | pkt->handler = &usbhs_fifo_pio_push_handler; | ||
421 | |||
422 | return pkt->handler->prepare(pkt, is_done); | ||
423 | } | ||
424 | |||
425 | struct usbhs_pkt_handle usbhs_dcp_data_stage_out_handler = { | ||
426 | .prepare = usbhsf_dcp_data_stage_try_push, | ||
427 | }; | ||
428 | |||
429 | /* | ||
430 | * DCP data stage (pop) | ||
431 | */ | ||
432 | static int usbhsf_dcp_data_stage_prepare_pop(struct usbhs_pkt *pkt, | ||
433 | int *is_done) | ||
434 | { | ||
435 | struct usbhs_pipe *pipe = pkt->pipe; | ||
436 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | ||
437 | struct usbhs_fifo *fifo = usbhsf_get_cfifo(priv); | ||
438 | |||
439 | if (usbhs_pipe_is_busy(pipe)) | ||
440 | return 0; | ||
441 | |||
442 | /* | ||
443 | * prepare pop for DCP should | ||
444 | * - change DCP direction, | ||
445 | * - clear fifo | ||
446 | * - DATA1 | ||
447 | */ | ||
448 | usbhs_pipe_disable(pipe); | ||
449 | |||
450 | usbhs_pipe_sequence_data1(pipe); /* DATA1 */ | ||
451 | |||
452 | usbhsf_fifo_select(pipe, fifo, 0); | ||
453 | usbhsf_fifo_clear(pipe, fifo); | ||
454 | usbhsf_fifo_unselect(pipe, fifo); | ||
455 | |||
456 | /* | ||
457 | * change handler to PIO pop | ||
458 | */ | ||
459 | pkt->handler = &usbhs_fifo_pio_pop_handler; | ||
460 | |||
461 | return pkt->handler->prepare(pkt, is_done); | ||
462 | } | ||
463 | |||
464 | struct usbhs_pkt_handle usbhs_dcp_data_stage_in_handler = { | ||
465 | .prepare = usbhsf_dcp_data_stage_prepare_pop, | ||
466 | }; | ||
467 | |||
468 | /* | ||
324 | * PIO push handler | 469 | * PIO push handler |
325 | */ | 470 | */ |
326 | static int usbhsf_pio_try_push(struct usbhs_pkt *pkt, int *is_done) | 471 | static int usbhsf_pio_try_push(struct usbhs_pkt *pkt, int *is_done) |
327 | { | 472 | { |
328 | struct usbhs_pipe *pipe = pkt->pipe; | 473 | struct usbhs_pipe *pipe = pkt->pipe; |
329 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | 474 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); |
330 | struct device *dev = usbhs_priv_to_dev(priv); | 475 | struct device *dev = usbhs_priv_to_dev(priv); |
331 | struct usbhs_fifo *fifo = usbhsf_get_cfifo(priv); /* CFIFO */ | 476 | struct usbhs_fifo *fifo = usbhsf_get_cfifo(priv); /* CFIFO */ |
332 | void __iomem *addr = priv->base + fifo->port; | 477 | void __iomem *addr = priv->base + fifo->port; |
333 | u8 *buf; | 478 | u8 *buf; |
334 | int maxp = usbhs_pipe_get_maxpacket(pipe); | 479 | int maxp = usbhs_pipe_get_maxpacket(pipe); |
335 | int total_len; | 480 | int total_len; |
336 | int i, ret, len; | 481 | int i, ret, len; |
337 | int is_short; | 482 | int is_short; |
338 | 483 | ||
339 | ret = usbhsf_fifo_select(pipe, fifo, 1); | 484 | ret = usbhsf_fifo_select(pipe, fifo, 1); |
340 | if (ret < 0) | 485 | if (ret < 0) |
341 | return 0; | 486 | return 0; |
342 | 487 | ||
343 | ret = usbhs_pipe_is_accessible(pipe); | 488 | ret = usbhs_pipe_is_accessible(pipe); |
344 | if (ret < 0) { | 489 | if (ret < 0) { |
345 | /* inaccessible pipe is not an error */ | 490 | /* inaccessible pipe is not an error */ |
346 | ret = 0; | 491 | ret = 0; |
347 | goto usbhs_fifo_write_busy; | 492 | goto usbhs_fifo_write_busy; |
348 | } | 493 | } |
349 | 494 | ||
350 | ret = usbhsf_fifo_barrier(priv, fifo); | 495 | ret = usbhsf_fifo_barrier(priv, fifo); |
351 | if (ret < 0) | 496 | if (ret < 0) |
352 | goto usbhs_fifo_write_busy; | 497 | goto usbhs_fifo_write_busy; |
353 | 498 | ||
354 | buf = pkt->buf + pkt->actual; | 499 | buf = pkt->buf + pkt->actual; |
355 | len = pkt->length - pkt->actual; | 500 | len = pkt->length - pkt->actual; |
356 | len = min(len, maxp); | 501 | len = min(len, maxp); |
357 | total_len = len; | 502 | total_len = len; |
358 | is_short = total_len < maxp; | 503 | is_short = total_len < maxp; |
359 | 504 | ||
360 | /* | 505 | /* |
361 | * FIXME | 506 | * FIXME |
362 | * | 507 | * |
363 | * 32-bit access only | 508 | * 32-bit access only |
364 | */ | 509 | */ |
365 | if (len >= 4 && !((unsigned long)buf & 0x03)) { | 510 | if (len >= 4 && !((unsigned long)buf & 0x03)) { |
366 | iowrite32_rep(addr, buf, len / 4); | 511 | iowrite32_rep(addr, buf, len / 4); |
367 | len %= 4; | 512 | len %= 4; |
368 | buf += total_len - len; | 513 | buf += total_len - len; |
369 | } | 514 | } |
370 | 515 | ||
371 | /* the rest operation */ | 516 | /* the rest operation */ |
372 | for (i = 0; i < len; i++) | 517 | for (i = 0; i < len; i++) |
373 | iowrite8(buf[i], addr + (0x03 - (i & 0x03))); | 518 | iowrite8(buf[i], addr + (0x03 - (i & 0x03))); |
374 | 519 | ||
375 | /* | 520 | /* |
376 | * variable update | 521 | * variable update |
377 | */ | 522 | */ |
378 | pkt->actual += total_len; | 523 | pkt->actual += total_len; |
379 | 524 | ||
380 | if (pkt->actual < pkt->length) | 525 | if (pkt->actual < pkt->length) |
381 | *is_done = 0; /* there are remainder data */ | 526 | *is_done = 0; /* there are remainder data */ |
382 | else if (is_short) | 527 | else if (is_short) |
383 | *is_done = 1; /* short packet */ | 528 | *is_done = 1; /* short packet */ |
384 | else | 529 | else |
385 | *is_done = !pkt->zero; /* send zero packet ? */ | 530 | *is_done = !pkt->zero; /* send zero packet ? */ |
386 | 531 | ||
387 | /* | 532 | /* |
388 | * pipe/irq handling | 533 | * pipe/irq handling |
389 | */ | 534 | */ |
390 | if (is_short) | 535 | if (is_short) |
391 | usbhsf_send_terminator(pipe, fifo); | 536 | usbhsf_send_terminator(pipe, fifo); |
392 | 537 | ||
393 | usbhsf_tx_irq_ctrl(pipe, !*is_done); | 538 | usbhsf_tx_irq_ctrl(pipe, !*is_done); |
394 | usbhs_pipe_enable(pipe); | 539 | usbhs_pipe_enable(pipe); |
395 | 540 | ||
396 | dev_dbg(dev, " send %d (%d/ %d/ %d/ %d)\n", | 541 | dev_dbg(dev, " send %d (%d/ %d/ %d/ %d)\n", |
397 | usbhs_pipe_number(pipe), | 542 | usbhs_pipe_number(pipe), |
398 | pkt->length, pkt->actual, *is_done, pkt->zero); | 543 | pkt->length, pkt->actual, *is_done, pkt->zero); |
399 | 544 | ||
400 | /* | 545 | /* |
401 | * Transmission end | 546 | * Transmission end |
402 | */ | 547 | */ |
403 | if (*is_done) { | 548 | if (*is_done) { |
404 | if (usbhs_pipe_is_dcp(pipe)) | 549 | if (usbhs_pipe_is_dcp(pipe)) |
405 | usbhs_dcp_control_transfer_done(pipe); | 550 | usbhs_dcp_control_transfer_done(pipe); |
406 | } | 551 | } |
407 | 552 | ||
408 | usbhsf_fifo_unselect(pipe, fifo); | 553 | usbhsf_fifo_unselect(pipe, fifo); |
409 | 554 | ||
410 | return 0; | 555 | return 0; |
411 | 556 | ||
412 | usbhs_fifo_write_busy: | 557 | usbhs_fifo_write_busy: |
413 | usbhsf_fifo_unselect(pipe, fifo); | 558 | usbhsf_fifo_unselect(pipe, fifo); |
414 | 559 | ||
415 | /* | 560 | /* |
416 | * pipe is busy. | 561 | * pipe is busy. |
417 | * retry in interrupt | 562 | * retry in interrupt |
418 | */ | 563 | */ |
419 | usbhsf_tx_irq_ctrl(pipe, 1); | 564 | usbhsf_tx_irq_ctrl(pipe, 1); |
420 | 565 | ||
421 | return ret; | 566 | return ret; |
422 | } | 567 | } |
423 | 568 | ||
424 | struct usbhs_pkt_handle usbhs_fifo_pio_push_handler = { | 569 | struct usbhs_pkt_handle usbhs_fifo_pio_push_handler = { |
425 | .prepare = usbhsf_pio_try_push, | 570 | .prepare = usbhsf_pio_try_push, |
426 | .try_run = usbhsf_pio_try_push, | 571 | .try_run = usbhsf_pio_try_push, |
427 | }; | 572 | }; |
428 | 573 | ||
429 | /* | 574 | /* |
430 | * PIO pop handler | 575 | * PIO pop handler |
431 | */ | 576 | */ |
432 | static int usbhsf_prepare_pop(struct usbhs_pkt *pkt, int *is_done) | 577 | static int usbhsf_prepare_pop(struct usbhs_pkt *pkt, int *is_done) |
433 | { | 578 | { |
434 | struct usbhs_pipe *pipe = pkt->pipe; | 579 | struct usbhs_pipe *pipe = pkt->pipe; |
435 | 580 | ||
436 | if (usbhs_pipe_is_busy(pipe)) | 581 | if (usbhs_pipe_is_busy(pipe)) |
437 | return 0; | 582 | return 0; |
438 | 583 | ||
439 | /* | 584 | /* |
440 | * pipe enable to prepare packet receive | 585 | * pipe enable to prepare packet receive |
441 | */ | 586 | */ |
442 | 587 | ||
443 | usbhs_pipe_enable(pipe); | 588 | usbhs_pipe_enable(pipe); |
444 | usbhsf_rx_irq_ctrl(pipe, 1); | 589 | usbhsf_rx_irq_ctrl(pipe, 1); |
445 | 590 | ||
446 | return 0; | 591 | return 0; |
447 | } | 592 | } |
448 | 593 | ||
449 | static int usbhsf_pio_try_pop(struct usbhs_pkt *pkt, int *is_done) | 594 | static int usbhsf_pio_try_pop(struct usbhs_pkt *pkt, int *is_done) |
450 | { | 595 | { |
451 | struct usbhs_pipe *pipe = pkt->pipe; | 596 | struct usbhs_pipe *pipe = pkt->pipe; |
452 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | 597 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); |
453 | struct device *dev = usbhs_priv_to_dev(priv); | 598 | struct device *dev = usbhs_priv_to_dev(priv); |
454 | struct usbhs_fifo *fifo = usbhsf_get_cfifo(priv); /* CFIFO */ | 599 | struct usbhs_fifo *fifo = usbhsf_get_cfifo(priv); /* CFIFO */ |
455 | void __iomem *addr = priv->base + fifo->port; | 600 | void __iomem *addr = priv->base + fifo->port; |
456 | u8 *buf; | 601 | u8 *buf; |
457 | u32 data = 0; | 602 | u32 data = 0; |
458 | int maxp = usbhs_pipe_get_maxpacket(pipe); | 603 | int maxp = usbhs_pipe_get_maxpacket(pipe); |
459 | int rcv_len, len; | 604 | int rcv_len, len; |
460 | int i, ret; | 605 | int i, ret; |
461 | int total_len = 0; | 606 | int total_len = 0; |
462 | 607 | ||
463 | ret = usbhsf_fifo_select(pipe, fifo, 0); | 608 | ret = usbhsf_fifo_select(pipe, fifo, 0); |
464 | if (ret < 0) | 609 | if (ret < 0) |
465 | return 0; | 610 | return 0; |
466 | 611 | ||
467 | ret = usbhsf_fifo_barrier(priv, fifo); | 612 | ret = usbhsf_fifo_barrier(priv, fifo); |
468 | if (ret < 0) | 613 | if (ret < 0) |
469 | goto usbhs_fifo_read_busy; | 614 | goto usbhs_fifo_read_busy; |
470 | 615 | ||
471 | rcv_len = usbhsf_fifo_rcv_len(priv, fifo); | 616 | rcv_len = usbhsf_fifo_rcv_len(priv, fifo); |
472 | 617 | ||
473 | buf = pkt->buf + pkt->actual; | 618 | buf = pkt->buf + pkt->actual; |
474 | len = pkt->length - pkt->actual; | 619 | len = pkt->length - pkt->actual; |
475 | len = min(len, rcv_len); | 620 | len = min(len, rcv_len); |
476 | total_len = len; | 621 | total_len = len; |
477 | 622 | ||
478 | /* | 623 | /* |
479 | * update actual length first here to decide disable pipe. | 624 | * update actual length first here to decide disable pipe. |
480 | * if this pipe keeps BUF status and all data were popped, | 625 | * if this pipe keeps BUF status and all data were popped, |
481 | * then, next interrupt/token will be issued again | 626 | * then, next interrupt/token will be issued again |
482 | */ | 627 | */ |
483 | pkt->actual += total_len; | 628 | pkt->actual += total_len; |
484 | 629 | ||
485 | if ((pkt->actual == pkt->length) || /* receive all data */ | 630 | if ((pkt->actual == pkt->length) || /* receive all data */ |
486 | (total_len < maxp)) { /* short packet */ | 631 | (total_len < maxp)) { /* short packet */ |
487 | *is_done = 1; | 632 | *is_done = 1; |
488 | usbhsf_rx_irq_ctrl(pipe, 0); | 633 | usbhsf_rx_irq_ctrl(pipe, 0); |
489 | usbhs_pipe_disable(pipe); /* disable pipe first */ | 634 | usbhs_pipe_disable(pipe); /* disable pipe first */ |
490 | } | 635 | } |
491 | 636 | ||
492 | /* | 637 | /* |
493 | * Buffer clear if Zero-Length packet | 638 | * Buffer clear if Zero-Length packet |
494 | * | 639 | * |
495 | * see | 640 | * see |
496 | * "Operation" - "FIFO Buffer Memory" - "FIFO Port Function" | 641 | * "Operation" - "FIFO Buffer Memory" - "FIFO Port Function" |
497 | */ | 642 | */ |
498 | if (0 == rcv_len) { | 643 | if (0 == rcv_len) { |
499 | usbhsf_fifo_clear(pipe, fifo); | 644 | usbhsf_fifo_clear(pipe, fifo); |
500 | goto usbhs_fifo_read_end; | 645 | goto usbhs_fifo_read_end; |
501 | } | 646 | } |
502 | 647 | ||
503 | /* | 648 | /* |
504 | * FIXME | 649 | * FIXME |
505 | * | 650 | * |
506 | * 32-bit access only | 651 | * 32-bit access only |
507 | */ | 652 | */ |
508 | if (len >= 4 && !((unsigned long)buf & 0x03)) { | 653 | if (len >= 4 && !((unsigned long)buf & 0x03)) { |
509 | ioread32_rep(addr, buf, len / 4); | 654 | ioread32_rep(addr, buf, len / 4); |
510 | len %= 4; | 655 | len %= 4; |
511 | buf += total_len - len; | 656 | buf += total_len - len; |
512 | } | 657 | } |
513 | 658 | ||
514 | /* the rest operation */ | 659 | /* the rest operation */ |
515 | for (i = 0; i < len; i++) { | 660 | for (i = 0; i < len; i++) { |
516 | if (!(i & 0x03)) | 661 | if (!(i & 0x03)) |
517 | data = ioread32(addr); | 662 | data = ioread32(addr); |
518 | 663 | ||
519 | buf[i] = (data >> ((i & 0x03) * 8)) & 0xff; | 664 | buf[i] = (data >> ((i & 0x03) * 8)) & 0xff; |
520 | } | 665 | } |
521 | 666 | ||
522 | usbhs_fifo_read_end: | 667 | usbhs_fifo_read_end: |
523 | dev_dbg(dev, " recv %d (%d/ %d/ %d/ %d)\n", | 668 | dev_dbg(dev, " recv %d (%d/ %d/ %d/ %d)\n", |
524 | usbhs_pipe_number(pipe), | 669 | usbhs_pipe_number(pipe), |
525 | pkt->length, pkt->actual, *is_done, pkt->zero); | 670 | pkt->length, pkt->actual, *is_done, pkt->zero); |
526 | 671 | ||
527 | usbhs_fifo_read_busy: | 672 | usbhs_fifo_read_busy: |
528 | usbhsf_fifo_unselect(pipe, fifo); | 673 | usbhsf_fifo_unselect(pipe, fifo); |
529 | 674 | ||
530 | return ret; | 675 | return ret; |
531 | } | 676 | } |
532 | 677 | ||
533 | struct usbhs_pkt_handle usbhs_fifo_pio_pop_handler = { | 678 | struct usbhs_pkt_handle usbhs_fifo_pio_pop_handler = { |
534 | .prepare = usbhsf_prepare_pop, | 679 | .prepare = usbhsf_prepare_pop, |
535 | .try_run = usbhsf_pio_try_pop, | 680 | .try_run = usbhsf_pio_try_pop, |
536 | }; | 681 | }; |
537 | 682 | ||
538 | /* | 683 | /* |
539 | * DCP ctrol statge handler | 684 | * DCP ctrol statge handler |
540 | */ | 685 | */ |
541 | static int usbhsf_ctrl_stage_end(struct usbhs_pkt *pkt, int *is_done) | 686 | static int usbhsf_ctrl_stage_end(struct usbhs_pkt *pkt, int *is_done) |
542 | { | 687 | { |
543 | usbhs_dcp_control_transfer_done(pkt->pipe); | 688 | usbhs_dcp_control_transfer_done(pkt->pipe); |
544 | 689 | ||
545 | *is_done = 1; | 690 | *is_done = 1; |
546 | 691 | ||
547 | return 0; | 692 | return 0; |
548 | } | 693 | } |
549 | 694 | ||
550 | struct usbhs_pkt_handle usbhs_ctrl_stage_end_handler = { | 695 | struct usbhs_pkt_handle usbhs_ctrl_stage_end_handler = { |
551 | .prepare = usbhsf_ctrl_stage_end, | 696 | .prepare = usbhsf_ctrl_stage_end, |
552 | .try_run = usbhsf_ctrl_stage_end, | 697 | .try_run = usbhsf_ctrl_stage_end, |
553 | }; | 698 | }; |
554 | 699 | ||
555 | /* | 700 | /* |
556 | * DMA fifo functions | 701 | * DMA fifo functions |
557 | */ | 702 | */ |
558 | static struct dma_chan *usbhsf_dma_chan_get(struct usbhs_fifo *fifo, | 703 | static struct dma_chan *usbhsf_dma_chan_get(struct usbhs_fifo *fifo, |
559 | struct usbhs_pkt *pkt) | 704 | struct usbhs_pkt *pkt) |
560 | { | 705 | { |
561 | if (&usbhs_fifo_dma_push_handler == pkt->handler) | 706 | if (&usbhs_fifo_dma_push_handler == pkt->handler) |
562 | return fifo->tx_chan; | 707 | return fifo->tx_chan; |
563 | 708 | ||
564 | if (&usbhs_fifo_dma_pop_handler == pkt->handler) | 709 | if (&usbhs_fifo_dma_pop_handler == pkt->handler) |
565 | return fifo->rx_chan; | 710 | return fifo->rx_chan; |
566 | 711 | ||
567 | return NULL; | 712 | return NULL; |
568 | } | 713 | } |
569 | 714 | ||
570 | static struct usbhs_fifo *usbhsf_get_dma_fifo(struct usbhs_priv *priv, | 715 | static struct usbhs_fifo *usbhsf_get_dma_fifo(struct usbhs_priv *priv, |
571 | struct usbhs_pkt *pkt) | 716 | struct usbhs_pkt *pkt) |
572 | { | 717 | { |
573 | struct usbhs_fifo *fifo; | 718 | struct usbhs_fifo *fifo; |
574 | 719 | ||
575 | /* DMA :: D0FIFO */ | 720 | /* DMA :: D0FIFO */ |
576 | fifo = usbhsf_get_d0fifo(priv); | 721 | fifo = usbhsf_get_d0fifo(priv); |
577 | if (usbhsf_dma_chan_get(fifo, pkt) && | 722 | if (usbhsf_dma_chan_get(fifo, pkt) && |
578 | !usbhsf_fifo_is_busy(fifo)) | 723 | !usbhsf_fifo_is_busy(fifo)) |
579 | return fifo; | 724 | return fifo; |
580 | 725 | ||
581 | /* DMA :: D1FIFO */ | 726 | /* DMA :: D1FIFO */ |
582 | fifo = usbhsf_get_d1fifo(priv); | 727 | fifo = usbhsf_get_d1fifo(priv); |
583 | if (usbhsf_dma_chan_get(fifo, pkt) && | 728 | if (usbhsf_dma_chan_get(fifo, pkt) && |
584 | !usbhsf_fifo_is_busy(fifo)) | 729 | !usbhsf_fifo_is_busy(fifo)) |
585 | return fifo; | 730 | return fifo; |
586 | 731 | ||
587 | return NULL; | 732 | return NULL; |
588 | } | 733 | } |
589 | 734 | ||
590 | #define usbhsf_dma_start(p, f) __usbhsf_dma_ctrl(p, f, DREQE) | 735 | #define usbhsf_dma_start(p, f) __usbhsf_dma_ctrl(p, f, DREQE) |
591 | #define usbhsf_dma_stop(p, f) __usbhsf_dma_ctrl(p, f, 0) | 736 | #define usbhsf_dma_stop(p, f) __usbhsf_dma_ctrl(p, f, 0) |
592 | static void __usbhsf_dma_ctrl(struct usbhs_pipe *pipe, | 737 | static void __usbhsf_dma_ctrl(struct usbhs_pipe *pipe, |
593 | struct usbhs_fifo *fifo, | 738 | struct usbhs_fifo *fifo, |
594 | u16 dreqe) | 739 | u16 dreqe) |
595 | { | 740 | { |
596 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | 741 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); |
597 | 742 | ||
598 | usbhs_bset(priv, fifo->sel, DREQE, dreqe); | 743 | usbhs_bset(priv, fifo->sel, DREQE, dreqe); |
599 | } | 744 | } |
600 | 745 | ||
601 | #define usbhsf_dma_map(p) __usbhsf_dma_map_ctrl(p, 1) | 746 | #define usbhsf_dma_map(p) __usbhsf_dma_map_ctrl(p, 1) |
602 | #define usbhsf_dma_unmap(p) __usbhsf_dma_map_ctrl(p, 0) | 747 | #define usbhsf_dma_unmap(p) __usbhsf_dma_map_ctrl(p, 0) |
603 | static int __usbhsf_dma_map_ctrl(struct usbhs_pkt *pkt, int map) | 748 | static int __usbhsf_dma_map_ctrl(struct usbhs_pkt *pkt, int map) |
604 | { | 749 | { |
605 | struct usbhs_pipe *pipe = pkt->pipe; | 750 | struct usbhs_pipe *pipe = pkt->pipe; |
606 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | 751 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); |
607 | struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv); | 752 | struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv); |
608 | 753 | ||
609 | return info->dma_map_ctrl(pkt, map); | 754 | return info->dma_map_ctrl(pkt, map); |
610 | } | 755 | } |
611 | 756 | ||
612 | static void usbhsf_dma_complete(void *arg); | 757 | static void usbhsf_dma_complete(void *arg); |
613 | static void usbhsf_dma_prepare_tasklet(unsigned long data) | 758 | static void usbhsf_dma_prepare_tasklet(unsigned long data) |
614 | { | 759 | { |
615 | struct usbhs_pkt *pkt = (struct usbhs_pkt *)data; | 760 | struct usbhs_pkt *pkt = (struct usbhs_pkt *)data; |
616 | struct usbhs_pipe *pipe = pkt->pipe; | 761 | struct usbhs_pipe *pipe = pkt->pipe; |
617 | struct usbhs_fifo *fifo = usbhs_pipe_to_fifo(pipe); | 762 | struct usbhs_fifo *fifo = usbhs_pipe_to_fifo(pipe); |
618 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | 763 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); |
619 | struct scatterlist sg; | 764 | struct scatterlist sg; |
620 | struct dma_async_tx_descriptor *desc; | 765 | struct dma_async_tx_descriptor *desc; |
621 | struct dma_chan *chan = usbhsf_dma_chan_get(fifo, pkt); | 766 | struct dma_chan *chan = usbhsf_dma_chan_get(fifo, pkt); |
622 | struct device *dev = usbhs_priv_to_dev(priv); | 767 | struct device *dev = usbhs_priv_to_dev(priv); |
623 | enum dma_data_direction dir; | 768 | enum dma_data_direction dir; |
624 | dma_cookie_t cookie; | 769 | dma_cookie_t cookie; |
625 | 770 | ||
626 | dir = usbhs_pipe_is_dir_in(pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE; | 771 | dir = usbhs_pipe_is_dir_in(pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE; |
627 | 772 | ||
628 | sg_init_table(&sg, 1); | 773 | sg_init_table(&sg, 1); |
629 | sg_set_page(&sg, virt_to_page(pkt->dma), | 774 | sg_set_page(&sg, virt_to_page(pkt->dma), |
630 | pkt->length, offset_in_page(pkt->dma)); | 775 | pkt->length, offset_in_page(pkt->dma)); |
631 | sg_dma_address(&sg) = pkt->dma + pkt->actual; | 776 | sg_dma_address(&sg) = pkt->dma + pkt->actual; |
632 | sg_dma_len(&sg) = pkt->trans; | 777 | sg_dma_len(&sg) = pkt->trans; |
633 | 778 | ||
634 | desc = chan->device->device_prep_slave_sg(chan, &sg, 1, dir, | 779 | desc = chan->device->device_prep_slave_sg(chan, &sg, 1, dir, |
635 | DMA_PREP_INTERRUPT | | 780 | DMA_PREP_INTERRUPT | |
636 | DMA_CTRL_ACK); | 781 | DMA_CTRL_ACK); |
637 | if (!desc) | 782 | if (!desc) |
638 | return; | 783 | return; |
639 | 784 | ||
640 | desc->callback = usbhsf_dma_complete; | 785 | desc->callback = usbhsf_dma_complete; |
641 | desc->callback_param = pipe; | 786 | desc->callback_param = pipe; |
642 | 787 | ||
643 | cookie = desc->tx_submit(desc); | 788 | cookie = desc->tx_submit(desc); |
644 | if (cookie < 0) { | 789 | if (cookie < 0) { |
645 | dev_err(dev, "Failed to submit dma descriptor\n"); | 790 | dev_err(dev, "Failed to submit dma descriptor\n"); |
646 | return; | 791 | return; |
647 | } | 792 | } |
648 | 793 | ||
649 | dev_dbg(dev, " %s %d (%d/ %d)\n", | 794 | dev_dbg(dev, " %s %d (%d/ %d)\n", |
650 | fifo->name, usbhs_pipe_number(pipe), pkt->length, pkt->zero); | 795 | fifo->name, usbhs_pipe_number(pipe), pkt->length, pkt->zero); |
651 | 796 | ||
652 | usbhsf_dma_start(pipe, fifo); | 797 | usbhsf_dma_start(pipe, fifo); |
653 | dma_async_issue_pending(chan); | 798 | dma_async_issue_pending(chan); |
654 | } | 799 | } |
655 | 800 | ||
656 | /* | 801 | /* |
657 | * DMA push handler | 802 | * DMA push handler |
658 | */ | 803 | */ |
659 | static int usbhsf_dma_prepare_push(struct usbhs_pkt *pkt, int *is_done) | 804 | static int usbhsf_dma_prepare_push(struct usbhs_pkt *pkt, int *is_done) |
660 | { | 805 | { |
661 | struct usbhs_pipe *pipe = pkt->pipe; | 806 | struct usbhs_pipe *pipe = pkt->pipe; |
662 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | 807 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); |
663 | struct usbhs_fifo *fifo; | 808 | struct usbhs_fifo *fifo; |
664 | int len = pkt->length - pkt->actual; | 809 | int len = pkt->length - pkt->actual; |
665 | int ret; | 810 | int ret; |
666 | 811 | ||
667 | if (usbhs_pipe_is_busy(pipe)) | 812 | if (usbhs_pipe_is_busy(pipe)) |
668 | return 0; | 813 | return 0; |
669 | 814 | ||
670 | /* use PIO if packet is less than pio_dma_border or pipe is DCP */ | 815 | /* use PIO if packet is less than pio_dma_border or pipe is DCP */ |
671 | if ((len < usbhs_get_dparam(priv, pio_dma_border)) || | 816 | if ((len < usbhs_get_dparam(priv, pio_dma_border)) || |
672 | usbhs_pipe_is_dcp(pipe)) | 817 | usbhs_pipe_is_dcp(pipe)) |
673 | goto usbhsf_pio_prepare_push; | 818 | goto usbhsf_pio_prepare_push; |
674 | 819 | ||
675 | if (len % 4) /* 32bit alignment */ | 820 | if (len % 4) /* 32bit alignment */ |
676 | goto usbhsf_pio_prepare_push; | 821 | goto usbhsf_pio_prepare_push; |
677 | 822 | ||
678 | if (((u32)pkt->buf + pkt->actual) & 0x7) /* 8byte alignment */ | 823 | if (((u32)pkt->buf + pkt->actual) & 0x7) /* 8byte alignment */ |
679 | goto usbhsf_pio_prepare_push; | 824 | goto usbhsf_pio_prepare_push; |
680 | 825 | ||
681 | /* get enable DMA fifo */ | 826 | /* get enable DMA fifo */ |
682 | fifo = usbhsf_get_dma_fifo(priv, pkt); | 827 | fifo = usbhsf_get_dma_fifo(priv, pkt); |
683 | if (!fifo) | 828 | if (!fifo) |
684 | goto usbhsf_pio_prepare_push; | 829 | goto usbhsf_pio_prepare_push; |
685 | 830 | ||
686 | if (usbhsf_dma_map(pkt) < 0) | 831 | if (usbhsf_dma_map(pkt) < 0) |
687 | goto usbhsf_pio_prepare_push; | 832 | goto usbhsf_pio_prepare_push; |
688 | 833 | ||
689 | ret = usbhsf_fifo_select(pipe, fifo, 0); | 834 | ret = usbhsf_fifo_select(pipe, fifo, 0); |
690 | if (ret < 0) | 835 | if (ret < 0) |
691 | goto usbhsf_pio_prepare_push_unmap; | 836 | goto usbhsf_pio_prepare_push_unmap; |
692 | 837 | ||
693 | pkt->trans = len; | 838 | pkt->trans = len; |
694 | 839 | ||
695 | tasklet_init(&fifo->tasklet, | 840 | tasklet_init(&fifo->tasklet, |
696 | usbhsf_dma_prepare_tasklet, | 841 | usbhsf_dma_prepare_tasklet, |
697 | (unsigned long)pkt); | 842 | (unsigned long)pkt); |
698 | 843 | ||
699 | tasklet_schedule(&fifo->tasklet); | 844 | tasklet_schedule(&fifo->tasklet); |
700 | 845 | ||
701 | return 0; | 846 | return 0; |
702 | 847 | ||
703 | usbhsf_pio_prepare_push_unmap: | 848 | usbhsf_pio_prepare_push_unmap: |
704 | usbhsf_dma_unmap(pkt); | 849 | usbhsf_dma_unmap(pkt); |
705 | usbhsf_pio_prepare_push: | 850 | usbhsf_pio_prepare_push: |
706 | /* | 851 | /* |
707 | * change handler to PIO | 852 | * change handler to PIO |
708 | */ | 853 | */ |
709 | pkt->handler = &usbhs_fifo_pio_push_handler; | 854 | pkt->handler = &usbhs_fifo_pio_push_handler; |
710 | 855 | ||
711 | return pkt->handler->prepare(pkt, is_done); | 856 | return pkt->handler->prepare(pkt, is_done); |
712 | } | 857 | } |
713 | 858 | ||
714 | static int usbhsf_dma_push_done(struct usbhs_pkt *pkt, int *is_done) | 859 | static int usbhsf_dma_push_done(struct usbhs_pkt *pkt, int *is_done) |
715 | { | 860 | { |
716 | struct usbhs_pipe *pipe = pkt->pipe; | 861 | struct usbhs_pipe *pipe = pkt->pipe; |
717 | 862 | ||
718 | pkt->actual = pkt->trans; | 863 | pkt->actual = pkt->trans; |
719 | 864 | ||
720 | *is_done = !pkt->zero; /* send zero packet ? */ | 865 | *is_done = !pkt->zero; /* send zero packet ? */ |
721 | 866 | ||
722 | usbhsf_dma_stop(pipe, pipe->fifo); | 867 | usbhsf_dma_stop(pipe, pipe->fifo); |
723 | usbhsf_dma_unmap(pkt); | 868 | usbhsf_dma_unmap(pkt); |
724 | usbhsf_fifo_unselect(pipe, pipe->fifo); | 869 | usbhsf_fifo_unselect(pipe, pipe->fifo); |
725 | 870 | ||
726 | return 0; | 871 | return 0; |
727 | } | 872 | } |
728 | 873 | ||
729 | struct usbhs_pkt_handle usbhs_fifo_dma_push_handler = { | 874 | struct usbhs_pkt_handle usbhs_fifo_dma_push_handler = { |
730 | .prepare = usbhsf_dma_prepare_push, | 875 | .prepare = usbhsf_dma_prepare_push, |
731 | .dma_done = usbhsf_dma_push_done, | 876 | .dma_done = usbhsf_dma_push_done, |
732 | }; | 877 | }; |
733 | 878 | ||
734 | /* | 879 | /* |
735 | * DMA pop handler | 880 | * DMA pop handler |
736 | */ | 881 | */ |
737 | static int usbhsf_dma_try_pop(struct usbhs_pkt *pkt, int *is_done) | 882 | static int usbhsf_dma_try_pop(struct usbhs_pkt *pkt, int *is_done) |
738 | { | 883 | { |
739 | struct usbhs_pipe *pipe = pkt->pipe; | 884 | struct usbhs_pipe *pipe = pkt->pipe; |
740 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | 885 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); |
741 | struct usbhs_fifo *fifo; | 886 | struct usbhs_fifo *fifo; |
742 | int len, ret; | 887 | int len, ret; |
743 | 888 | ||
744 | if (usbhs_pipe_is_busy(pipe)) | 889 | if (usbhs_pipe_is_busy(pipe)) |
745 | return 0; | 890 | return 0; |
746 | 891 | ||
747 | if (usbhs_pipe_is_dcp(pipe)) | 892 | if (usbhs_pipe_is_dcp(pipe)) |
748 | goto usbhsf_pio_prepare_pop; | 893 | goto usbhsf_pio_prepare_pop; |
749 | 894 | ||
750 | /* get enable DMA fifo */ | 895 | /* get enable DMA fifo */ |
751 | fifo = usbhsf_get_dma_fifo(priv, pkt); | 896 | fifo = usbhsf_get_dma_fifo(priv, pkt); |
752 | if (!fifo) | 897 | if (!fifo) |
753 | goto usbhsf_pio_prepare_pop; | 898 | goto usbhsf_pio_prepare_pop; |
754 | 899 | ||
755 | if (((u32)pkt->buf + pkt->actual) & 0x7) /* 8byte alignment */ | 900 | if (((u32)pkt->buf + pkt->actual) & 0x7) /* 8byte alignment */ |
756 | goto usbhsf_pio_prepare_pop; | 901 | goto usbhsf_pio_prepare_pop; |
757 | 902 | ||
758 | ret = usbhsf_fifo_select(pipe, fifo, 0); | 903 | ret = usbhsf_fifo_select(pipe, fifo, 0); |
759 | if (ret < 0) | 904 | if (ret < 0) |
760 | goto usbhsf_pio_prepare_pop; | 905 | goto usbhsf_pio_prepare_pop; |
761 | 906 | ||
762 | /* use PIO if packet is less than pio_dma_border */ | 907 | /* use PIO if packet is less than pio_dma_border */ |
763 | len = usbhsf_fifo_rcv_len(priv, fifo); | 908 | len = usbhsf_fifo_rcv_len(priv, fifo); |
764 | len = min(pkt->length - pkt->actual, len); | 909 | len = min(pkt->length - pkt->actual, len); |
765 | if (len % 4) /* 32bit alignment */ | 910 | if (len % 4) /* 32bit alignment */ |
766 | goto usbhsf_pio_prepare_pop_unselect; | 911 | goto usbhsf_pio_prepare_pop_unselect; |
767 | 912 | ||
768 | if (len < usbhs_get_dparam(priv, pio_dma_border)) | 913 | if (len < usbhs_get_dparam(priv, pio_dma_border)) |
769 | goto usbhsf_pio_prepare_pop_unselect; | 914 | goto usbhsf_pio_prepare_pop_unselect; |
770 | 915 | ||
771 | ret = usbhsf_fifo_barrier(priv, fifo); | 916 | ret = usbhsf_fifo_barrier(priv, fifo); |
772 | if (ret < 0) | 917 | if (ret < 0) |
773 | goto usbhsf_pio_prepare_pop_unselect; | 918 | goto usbhsf_pio_prepare_pop_unselect; |
774 | 919 | ||
775 | if (usbhsf_dma_map(pkt) < 0) | 920 | if (usbhsf_dma_map(pkt) < 0) |
776 | goto usbhsf_pio_prepare_pop_unselect; | 921 | goto usbhsf_pio_prepare_pop_unselect; |
777 | 922 | ||
778 | /* DMA */ | 923 | /* DMA */ |
779 | 924 | ||
780 | /* | 925 | /* |
781 | * usbhs_fifo_dma_pop_handler :: prepare | 926 | * usbhs_fifo_dma_pop_handler :: prepare |
782 | * enabled irq to come here. | 927 | * enabled irq to come here. |
783 | * but it is no longer needed for DMA. disable it. | 928 | * but it is no longer needed for DMA. disable it. |
784 | */ | 929 | */ |
785 | usbhsf_rx_irq_ctrl(pipe, 0); | 930 | usbhsf_rx_irq_ctrl(pipe, 0); |
786 | 931 | ||
787 | pkt->trans = len; | 932 | pkt->trans = len; |
788 | 933 | ||
789 | tasklet_init(&fifo->tasklet, | 934 | tasklet_init(&fifo->tasklet, |
790 | usbhsf_dma_prepare_tasklet, | 935 | usbhsf_dma_prepare_tasklet, |
791 | (unsigned long)pkt); | 936 | (unsigned long)pkt); |
792 | 937 | ||
793 | tasklet_schedule(&fifo->tasklet); | 938 | tasklet_schedule(&fifo->tasklet); |
794 | 939 | ||
795 | return 0; | 940 | return 0; |
796 | 941 | ||
797 | usbhsf_pio_prepare_pop_unselect: | 942 | usbhsf_pio_prepare_pop_unselect: |
798 | usbhsf_fifo_unselect(pipe, fifo); | 943 | usbhsf_fifo_unselect(pipe, fifo); |
799 | usbhsf_pio_prepare_pop: | 944 | usbhsf_pio_prepare_pop: |
800 | 945 | ||
801 | /* | 946 | /* |
802 | * change handler to PIO | 947 | * change handler to PIO |
803 | */ | 948 | */ |
804 | pkt->handler = &usbhs_fifo_pio_pop_handler; | 949 | pkt->handler = &usbhs_fifo_pio_pop_handler; |
805 | 950 | ||
806 | return pkt->handler->try_run(pkt, is_done); | 951 | return pkt->handler->try_run(pkt, is_done); |
807 | } | 952 | } |
808 | 953 | ||
809 | static int usbhsf_dma_pop_done(struct usbhs_pkt *pkt, int *is_done) | 954 | static int usbhsf_dma_pop_done(struct usbhs_pkt *pkt, int *is_done) |
810 | { | 955 | { |
811 | struct usbhs_pipe *pipe = pkt->pipe; | 956 | struct usbhs_pipe *pipe = pkt->pipe; |
812 | int maxp = usbhs_pipe_get_maxpacket(pipe); | 957 | int maxp = usbhs_pipe_get_maxpacket(pipe); |
813 | 958 | ||
814 | usbhsf_dma_stop(pipe, pipe->fifo); | 959 | usbhsf_dma_stop(pipe, pipe->fifo); |
815 | usbhsf_dma_unmap(pkt); | 960 | usbhsf_dma_unmap(pkt); |
816 | usbhsf_fifo_unselect(pipe, pipe->fifo); | 961 | usbhsf_fifo_unselect(pipe, pipe->fifo); |
817 | 962 | ||
818 | pkt->actual += pkt->trans; | 963 | pkt->actual += pkt->trans; |
819 | 964 | ||
820 | if ((pkt->actual == pkt->length) || /* receive all data */ | 965 | if ((pkt->actual == pkt->length) || /* receive all data */ |
821 | (pkt->trans < maxp)) { /* short packet */ | 966 | (pkt->trans < maxp)) { /* short packet */ |
822 | *is_done = 1; | 967 | *is_done = 1; |
823 | } else { | 968 | } else { |
824 | /* re-enable */ | 969 | /* re-enable */ |
825 | usbhsf_prepare_pop(pkt, is_done); | 970 | usbhsf_prepare_pop(pkt, is_done); |
826 | } | 971 | } |
827 | 972 | ||
828 | return 0; | 973 | return 0; |
829 | } | 974 | } |
830 | 975 | ||
831 | struct usbhs_pkt_handle usbhs_fifo_dma_pop_handler = { | 976 | struct usbhs_pkt_handle usbhs_fifo_dma_pop_handler = { |
832 | .prepare = usbhsf_prepare_pop, | 977 | .prepare = usbhsf_prepare_pop, |
833 | .try_run = usbhsf_dma_try_pop, | 978 | .try_run = usbhsf_dma_try_pop, |
834 | .dma_done = usbhsf_dma_pop_done | 979 | .dma_done = usbhsf_dma_pop_done |
835 | }; | 980 | }; |
836 | 981 | ||
837 | /* | 982 | /* |
838 | * DMA setting | 983 | * DMA setting |
839 | */ | 984 | */ |
840 | static bool usbhsf_dma_filter(struct dma_chan *chan, void *param) | 985 | static bool usbhsf_dma_filter(struct dma_chan *chan, void *param) |
841 | { | 986 | { |
842 | struct sh_dmae_slave *slave = param; | 987 | struct sh_dmae_slave *slave = param; |
843 | 988 | ||
844 | /* | 989 | /* |
845 | * FIXME | 990 | * FIXME |
846 | * | 991 | * |
847 | * usbhs doesn't recognize id = 0 as valid DMA | 992 | * usbhs doesn't recognize id = 0 as valid DMA |
848 | */ | 993 | */ |
849 | if (0 == slave->slave_id) | 994 | if (0 == slave->slave_id) |
850 | return false; | 995 | return false; |
851 | 996 | ||
852 | chan->private = slave; | 997 | chan->private = slave; |
853 | 998 | ||
854 | return true; | 999 | return true; |
855 | } | 1000 | } |
856 | 1001 | ||
857 | static void usbhsf_dma_quit(struct usbhs_priv *priv, struct usbhs_fifo *fifo) | 1002 | static void usbhsf_dma_quit(struct usbhs_priv *priv, struct usbhs_fifo *fifo) |
858 | { | 1003 | { |
859 | if (fifo->tx_chan) | 1004 | if (fifo->tx_chan) |
860 | dma_release_channel(fifo->tx_chan); | 1005 | dma_release_channel(fifo->tx_chan); |
861 | if (fifo->rx_chan) | 1006 | if (fifo->rx_chan) |
862 | dma_release_channel(fifo->rx_chan); | 1007 | dma_release_channel(fifo->rx_chan); |
863 | 1008 | ||
864 | fifo->tx_chan = NULL; | 1009 | fifo->tx_chan = NULL; |
865 | fifo->rx_chan = NULL; | 1010 | fifo->rx_chan = NULL; |
866 | } | 1011 | } |
867 | 1012 | ||
868 | static void usbhsf_dma_init(struct usbhs_priv *priv, | 1013 | static void usbhsf_dma_init(struct usbhs_priv *priv, |
869 | struct usbhs_fifo *fifo) | 1014 | struct usbhs_fifo *fifo) |
870 | { | 1015 | { |
871 | struct device *dev = usbhs_priv_to_dev(priv); | 1016 | struct device *dev = usbhs_priv_to_dev(priv); |
872 | dma_cap_mask_t mask; | 1017 | dma_cap_mask_t mask; |
873 | 1018 | ||
874 | dma_cap_zero(mask); | 1019 | dma_cap_zero(mask); |
875 | dma_cap_set(DMA_SLAVE, mask); | 1020 | dma_cap_set(DMA_SLAVE, mask); |
876 | fifo->tx_chan = dma_request_channel(mask, usbhsf_dma_filter, | 1021 | fifo->tx_chan = dma_request_channel(mask, usbhsf_dma_filter, |
877 | &fifo->tx_slave); | 1022 | &fifo->tx_slave); |
878 | 1023 | ||
879 | dma_cap_zero(mask); | 1024 | dma_cap_zero(mask); |
880 | dma_cap_set(DMA_SLAVE, mask); | 1025 | dma_cap_set(DMA_SLAVE, mask); |
881 | fifo->rx_chan = dma_request_channel(mask, usbhsf_dma_filter, | 1026 | fifo->rx_chan = dma_request_channel(mask, usbhsf_dma_filter, |
882 | &fifo->rx_slave); | 1027 | &fifo->rx_slave); |
883 | 1028 | ||
884 | if (fifo->tx_chan || fifo->rx_chan) | 1029 | if (fifo->tx_chan || fifo->rx_chan) |
885 | dev_dbg(dev, "enable DMAEngine (%s%s%s)\n", | 1030 | dev_dbg(dev, "enable DMAEngine (%s%s%s)\n", |
886 | fifo->name, | 1031 | fifo->name, |
887 | fifo->tx_chan ? "[TX]" : " ", | 1032 | fifo->tx_chan ? "[TX]" : " ", |
888 | fifo->rx_chan ? "[RX]" : " "); | 1033 | fifo->rx_chan ? "[RX]" : " "); |
889 | } | 1034 | } |
890 | 1035 | ||
891 | /* | 1036 | /* |
892 | * irq functions | 1037 | * irq functions |
893 | */ | 1038 | */ |
894 | static int usbhsf_irq_empty(struct usbhs_priv *priv, | 1039 | static int usbhsf_irq_empty(struct usbhs_priv *priv, |
895 | struct usbhs_irq_state *irq_state) | 1040 | struct usbhs_irq_state *irq_state) |
896 | { | 1041 | { |
897 | struct usbhs_pipe *pipe; | 1042 | struct usbhs_pipe *pipe; |
898 | struct device *dev = usbhs_priv_to_dev(priv); | 1043 | struct device *dev = usbhs_priv_to_dev(priv); |
899 | int i, ret; | 1044 | int i, ret; |
900 | 1045 | ||
901 | if (!irq_state->bempsts) { | 1046 | if (!irq_state->bempsts) { |
902 | dev_err(dev, "debug %s !!\n", __func__); | 1047 | dev_err(dev, "debug %s !!\n", __func__); |
903 | return -EIO; | 1048 | return -EIO; |
904 | } | 1049 | } |
905 | 1050 | ||
906 | dev_dbg(dev, "irq empty [0x%04x]\n", irq_state->bempsts); | 1051 | dev_dbg(dev, "irq empty [0x%04x]\n", irq_state->bempsts); |
907 | 1052 | ||
908 | /* | 1053 | /* |
909 | * search interrupted "pipe" | 1054 | * search interrupted "pipe" |
910 | * not "uep". | 1055 | * not "uep". |
911 | */ | 1056 | */ |
912 | usbhs_for_each_pipe_with_dcp(pipe, priv, i) { | 1057 | usbhs_for_each_pipe_with_dcp(pipe, priv, i) { |
913 | if (!(irq_state->bempsts & (1 << i))) | 1058 | if (!(irq_state->bempsts & (1 << i))) |
914 | continue; | 1059 | continue; |
915 | 1060 | ||
916 | ret = usbhsf_pkt_handler(pipe, USBHSF_PKT_TRY_RUN); | 1061 | ret = usbhsf_pkt_handler(pipe, USBHSF_PKT_TRY_RUN); |
917 | if (ret < 0) | 1062 | if (ret < 0) |
918 | dev_err(dev, "irq_empty run_error %d : %d\n", i, ret); | 1063 | dev_err(dev, "irq_empty run_error %d : %d\n", i, ret); |
919 | } | 1064 | } |
920 | 1065 | ||
921 | return 0; | 1066 | return 0; |
922 | } | 1067 | } |
923 | 1068 | ||
924 | static int usbhsf_irq_ready(struct usbhs_priv *priv, | 1069 | static int usbhsf_irq_ready(struct usbhs_priv *priv, |
925 | struct usbhs_irq_state *irq_state) | 1070 | struct usbhs_irq_state *irq_state) |
926 | { | 1071 | { |
927 | struct usbhs_pipe *pipe; | 1072 | struct usbhs_pipe *pipe; |
928 | struct device *dev = usbhs_priv_to_dev(priv); | 1073 | struct device *dev = usbhs_priv_to_dev(priv); |
929 | int i, ret; | 1074 | int i, ret; |
930 | 1075 | ||
931 | if (!irq_state->brdysts) { | 1076 | if (!irq_state->brdysts) { |
932 | dev_err(dev, "debug %s !!\n", __func__); | 1077 | dev_err(dev, "debug %s !!\n", __func__); |
933 | return -EIO; | 1078 | return -EIO; |
934 | } | 1079 | } |
935 | 1080 | ||
936 | dev_dbg(dev, "irq ready [0x%04x]\n", irq_state->brdysts); | 1081 | dev_dbg(dev, "irq ready [0x%04x]\n", irq_state->brdysts); |
937 | 1082 | ||
938 | /* | 1083 | /* |
939 | * search interrupted "pipe" | 1084 | * search interrupted "pipe" |
940 | * not "uep". | 1085 | * not "uep". |
941 | */ | 1086 | */ |
942 | usbhs_for_each_pipe_with_dcp(pipe, priv, i) { | 1087 | usbhs_for_each_pipe_with_dcp(pipe, priv, i) { |
943 | if (!(irq_state->brdysts & (1 << i))) | 1088 | if (!(irq_state->brdysts & (1 << i))) |
944 | continue; | 1089 | continue; |
945 | 1090 | ||
946 | ret = usbhsf_pkt_handler(pipe, USBHSF_PKT_TRY_RUN); | 1091 | ret = usbhsf_pkt_handler(pipe, USBHSF_PKT_TRY_RUN); |
947 | if (ret < 0) | 1092 | if (ret < 0) |
948 | dev_err(dev, "irq_ready run_error %d : %d\n", i, ret); | 1093 | dev_err(dev, "irq_ready run_error %d : %d\n", i, ret); |
949 | } | 1094 | } |
950 | 1095 | ||
951 | return 0; | 1096 | return 0; |
952 | } | 1097 | } |
953 | 1098 | ||
954 | static void usbhsf_dma_complete(void *arg) | 1099 | static void usbhsf_dma_complete(void *arg) |
955 | { | 1100 | { |
956 | struct usbhs_pipe *pipe = arg; | 1101 | struct usbhs_pipe *pipe = arg; |
957 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | 1102 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); |
958 | struct device *dev = usbhs_priv_to_dev(priv); | 1103 | struct device *dev = usbhs_priv_to_dev(priv); |
959 | int ret; | 1104 | int ret; |
960 | 1105 | ||
961 | ret = usbhsf_pkt_handler(pipe, USBHSF_PKT_DMA_DONE); | 1106 | ret = usbhsf_pkt_handler(pipe, USBHSF_PKT_DMA_DONE); |
962 | if (ret < 0) | 1107 | if (ret < 0) |
963 | dev_err(dev, "dma_complete run_error %d : %d\n", | 1108 | dev_err(dev, "dma_complete run_error %d : %d\n", |
964 | usbhs_pipe_number(pipe), ret); | 1109 | usbhs_pipe_number(pipe), ret); |
965 | } | 1110 | } |
966 | 1111 | ||
967 | /* | 1112 | /* |
968 | * fifo init | 1113 | * fifo init |
969 | */ | 1114 | */ |
970 | void usbhs_fifo_init(struct usbhs_priv *priv) | 1115 | void usbhs_fifo_init(struct usbhs_priv *priv) |
971 | { | 1116 | { |
972 | struct usbhs_mod *mod = usbhs_mod_get_current(priv); | 1117 | struct usbhs_mod *mod = usbhs_mod_get_current(priv); |
973 | struct usbhs_fifo *cfifo = usbhsf_get_cfifo(priv); | 1118 | struct usbhs_fifo *cfifo = usbhsf_get_cfifo(priv); |
974 | struct usbhs_fifo *d0fifo = usbhsf_get_d0fifo(priv); | 1119 | struct usbhs_fifo *d0fifo = usbhsf_get_d0fifo(priv); |
975 | struct usbhs_fifo *d1fifo = usbhsf_get_d1fifo(priv); | 1120 | struct usbhs_fifo *d1fifo = usbhsf_get_d1fifo(priv); |
976 | 1121 | ||
977 | mod->irq_empty = usbhsf_irq_empty; | 1122 | mod->irq_empty = usbhsf_irq_empty; |
978 | mod->irq_ready = usbhsf_irq_ready; | 1123 | mod->irq_ready = usbhsf_irq_ready; |
979 | mod->irq_bempsts = 0; | 1124 | mod->irq_bempsts = 0; |
980 | mod->irq_brdysts = 0; | 1125 | mod->irq_brdysts = 0; |
981 | 1126 | ||
982 | cfifo->pipe = NULL; | 1127 | cfifo->pipe = NULL; |
983 | cfifo->tx_chan = NULL; | 1128 | cfifo->tx_chan = NULL; |
984 | cfifo->rx_chan = NULL; | 1129 | cfifo->rx_chan = NULL; |
985 | 1130 | ||
986 | d0fifo->pipe = NULL; | 1131 | d0fifo->pipe = NULL; |
987 | d0fifo->tx_chan = NULL; | 1132 | d0fifo->tx_chan = NULL; |
988 | d0fifo->rx_chan = NULL; | 1133 | d0fifo->rx_chan = NULL; |
989 | 1134 | ||
990 | d1fifo->pipe = NULL; | 1135 | d1fifo->pipe = NULL; |
991 | d1fifo->tx_chan = NULL; | 1136 | d1fifo->tx_chan = NULL; |
992 | d1fifo->rx_chan = NULL; | 1137 | d1fifo->rx_chan = NULL; |
993 | 1138 | ||
994 | usbhsf_dma_init(priv, usbhsf_get_d0fifo(priv)); | 1139 | usbhsf_dma_init(priv, usbhsf_get_d0fifo(priv)); |
995 | usbhsf_dma_init(priv, usbhsf_get_d1fifo(priv)); | 1140 | usbhsf_dma_init(priv, usbhsf_get_d1fifo(priv)); |
996 | } | 1141 | } |
997 | 1142 | ||
998 | void usbhs_fifo_quit(struct usbhs_priv *priv) | 1143 | void usbhs_fifo_quit(struct usbhs_priv *priv) |
999 | { | 1144 | { |
1000 | struct usbhs_mod *mod = usbhs_mod_get_current(priv); | 1145 | struct usbhs_mod *mod = usbhs_mod_get_current(priv); |
1001 | 1146 | ||
1002 | mod->irq_empty = NULL; | 1147 | mod->irq_empty = NULL; |
1003 | mod->irq_ready = NULL; | 1148 | mod->irq_ready = NULL; |
1004 | mod->irq_bempsts = 0; | 1149 | mod->irq_bempsts = 0; |
1005 | mod->irq_brdysts = 0; | 1150 | mod->irq_brdysts = 0; |
1006 | 1151 | ||
1007 | usbhsf_dma_quit(priv, usbhsf_get_d0fifo(priv)); | 1152 | usbhsf_dma_quit(priv, usbhsf_get_d0fifo(priv)); |
1008 | usbhsf_dma_quit(priv, usbhsf_get_d1fifo(priv)); | 1153 | usbhsf_dma_quit(priv, usbhsf_get_d1fifo(priv)); |
1009 | } | 1154 | } |
1010 | 1155 | ||
1011 | int usbhs_fifo_probe(struct usbhs_priv *priv) | 1156 | int usbhs_fifo_probe(struct usbhs_priv *priv) |
1012 | { | 1157 | { |
1013 | struct usbhs_fifo *fifo; | 1158 | struct usbhs_fifo *fifo; |
1014 | 1159 | ||
1015 | /* CFIFO */ | 1160 | /* CFIFO */ |
1016 | fifo = usbhsf_get_cfifo(priv); | 1161 | fifo = usbhsf_get_cfifo(priv); |
1017 | fifo->name = "CFIFO"; | 1162 | fifo->name = "CFIFO"; |
1018 | fifo->port = CFIFO; | 1163 | fifo->port = CFIFO; |
1019 | fifo->sel = CFIFOSEL; | 1164 | fifo->sel = CFIFOSEL; |
1020 | fifo->ctr = CFIFOCTR; | 1165 | fifo->ctr = CFIFOCTR; |
1021 | 1166 | ||
1022 | /* D0FIFO */ | 1167 | /* D0FIFO */ |
1023 | fifo = usbhsf_get_d0fifo(priv); | 1168 | fifo = usbhsf_get_d0fifo(priv); |
1024 | fifo->name = "D0FIFO"; | 1169 | fifo->name = "D0FIFO"; |
1025 | fifo->port = D0FIFO; | 1170 | fifo->port = D0FIFO; |
1026 | fifo->sel = D0FIFOSEL; | 1171 | fifo->sel = D0FIFOSEL; |
1027 | fifo->ctr = D0FIFOCTR; | 1172 | fifo->ctr = D0FIFOCTR; |
1028 | fifo->tx_slave.slave_id = usbhs_get_dparam(priv, d0_tx_id); | 1173 | fifo->tx_slave.slave_id = usbhs_get_dparam(priv, d0_tx_id); |
1029 | fifo->rx_slave.slave_id = usbhs_get_dparam(priv, d0_rx_id); | 1174 | fifo->rx_slave.slave_id = usbhs_get_dparam(priv, d0_rx_id); |
1030 | 1175 | ||
1031 | /* D1FIFO */ | 1176 | /* D1FIFO */ |
1032 | fifo = usbhsf_get_d1fifo(priv); | 1177 | fifo = usbhsf_get_d1fifo(priv); |
1033 | fifo->name = "D1FIFO"; | 1178 | fifo->name = "D1FIFO"; |
1034 | fifo->port = D1FIFO; | 1179 | fifo->port = D1FIFO; |
1035 | fifo->sel = D1FIFOSEL; | 1180 | fifo->sel = D1FIFOSEL; |
1036 | fifo->ctr = D1FIFOCTR; | 1181 | fifo->ctr = D1FIFOCTR; |
1037 | fifo->tx_slave.slave_id = usbhs_get_dparam(priv, d1_tx_id); | 1182 | fifo->tx_slave.slave_id = usbhs_get_dparam(priv, d1_tx_id); |
1038 | fifo->rx_slave.slave_id = usbhs_get_dparam(priv, d1_rx_id); | 1183 | fifo->rx_slave.slave_id = usbhs_get_dparam(priv, d1_rx_id); |
1039 | 1184 | ||
1040 | return 0; | 1185 | return 0; |
1041 | } | 1186 | } |
1042 | 1187 | ||
1043 | void usbhs_fifo_remove(struct usbhs_priv *priv) | 1188 | void usbhs_fifo_remove(struct usbhs_priv *priv) |
1044 | { | 1189 | { |
1045 | } | 1190 | } |
1046 | 1191 |
drivers/usb/renesas_usbhs/fifo.h
1 | /* | 1 | /* |
2 | * Renesas USB driver | 2 | * Renesas USB driver |
3 | * | 3 | * |
4 | * Copyright (C) 2011 Renesas Solutions Corp. | 4 | * Copyright (C) 2011 Renesas Solutions Corp. |
5 | * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | 5 | * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> |
6 | * | 6 | * |
7 | * This program is distributed in the hope that it will be useful, | 7 | * This program is distributed in the hope that it will be useful, |
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
10 | * GNU General Public License for more details. | 10 | * GNU General Public License for more details. |
11 | * | 11 | * |
12 | * You should have received a copy of the GNU General Public License | 12 | * You should have received a copy of the GNU General Public License |
13 | * along with this program; if not, write to the Free Software | 13 | * along with this program; if not, write to the Free Software |
14 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 14 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
15 | * | 15 | * |
16 | */ | 16 | */ |
17 | #ifndef RENESAS_USB_FIFO_H | 17 | #ifndef RENESAS_USB_FIFO_H |
18 | #define RENESAS_USB_FIFO_H | 18 | #define RENESAS_USB_FIFO_H |
19 | 19 | ||
20 | #include <linux/interrupt.h> | 20 | #include <linux/interrupt.h> |
21 | #include <linux/sh_dma.h> | 21 | #include <linux/sh_dma.h> |
22 | #include <asm/dma.h> | 22 | #include <asm/dma.h> |
23 | #include "pipe.h" | 23 | #include "pipe.h" |
24 | 24 | ||
25 | #define DMA_ADDR_INVALID (~(dma_addr_t)0) | 25 | #define DMA_ADDR_INVALID (~(dma_addr_t)0) |
26 | 26 | ||
27 | struct usbhs_fifo { | 27 | struct usbhs_fifo { |
28 | char *name; | 28 | char *name; |
29 | u32 port; /* xFIFO */ | 29 | u32 port; /* xFIFO */ |
30 | u32 sel; /* xFIFOSEL */ | 30 | u32 sel; /* xFIFOSEL */ |
31 | u32 ctr; /* xFIFOCTR */ | 31 | u32 ctr; /* xFIFOCTR */ |
32 | 32 | ||
33 | struct usbhs_pipe *pipe; | 33 | struct usbhs_pipe *pipe; |
34 | struct tasklet_struct tasklet; | 34 | struct tasklet_struct tasklet; |
35 | 35 | ||
36 | struct dma_chan *tx_chan; | 36 | struct dma_chan *tx_chan; |
37 | struct dma_chan *rx_chan; | 37 | struct dma_chan *rx_chan; |
38 | 38 | ||
39 | struct sh_dmae_slave tx_slave; | 39 | struct sh_dmae_slave tx_slave; |
40 | struct sh_dmae_slave rx_slave; | 40 | struct sh_dmae_slave rx_slave; |
41 | }; | 41 | }; |
42 | 42 | ||
43 | struct usbhs_fifo_info { | 43 | struct usbhs_fifo_info { |
44 | struct usbhs_fifo cfifo; | 44 | struct usbhs_fifo cfifo; |
45 | struct usbhs_fifo d0fifo; | 45 | struct usbhs_fifo d0fifo; |
46 | struct usbhs_fifo d1fifo; | 46 | struct usbhs_fifo d1fifo; |
47 | }; | 47 | }; |
48 | 48 | ||
49 | struct usbhs_pkt_handle; | 49 | struct usbhs_pkt_handle; |
50 | struct usbhs_pkt { | 50 | struct usbhs_pkt { |
51 | struct list_head node; | 51 | struct list_head node; |
52 | struct usbhs_pipe *pipe; | 52 | struct usbhs_pipe *pipe; |
53 | struct usbhs_pkt_handle *handler; | 53 | struct usbhs_pkt_handle *handler; |
54 | void (*done)(struct usbhs_priv *priv, | 54 | void (*done)(struct usbhs_priv *priv, |
55 | struct usbhs_pkt *pkt); | 55 | struct usbhs_pkt *pkt); |
56 | dma_addr_t dma; | 56 | dma_addr_t dma; |
57 | void *buf; | 57 | void *buf; |
58 | int length; | 58 | int length; |
59 | int trans; | 59 | int trans; |
60 | int actual; | 60 | int actual; |
61 | int zero; | 61 | int zero; |
62 | }; | 62 | }; |
63 | 63 | ||
64 | struct usbhs_pkt_handle { | 64 | struct usbhs_pkt_handle { |
65 | int (*prepare)(struct usbhs_pkt *pkt, int *is_done); | 65 | int (*prepare)(struct usbhs_pkt *pkt, int *is_done); |
66 | int (*try_run)(struct usbhs_pkt *pkt, int *is_done); | 66 | int (*try_run)(struct usbhs_pkt *pkt, int *is_done); |
67 | int (*dma_done)(struct usbhs_pkt *pkt, int *is_done); | 67 | int (*dma_done)(struct usbhs_pkt *pkt, int *is_done); |
68 | }; | 68 | }; |
69 | 69 | ||
70 | /* | 70 | /* |
71 | * fifo | 71 | * fifo |
72 | */ | 72 | */ |
73 | int usbhs_fifo_probe(struct usbhs_priv *priv); | 73 | int usbhs_fifo_probe(struct usbhs_priv *priv); |
74 | void usbhs_fifo_remove(struct usbhs_priv *priv); | 74 | void usbhs_fifo_remove(struct usbhs_priv *priv); |
75 | void usbhs_fifo_init(struct usbhs_priv *priv); | 75 | void usbhs_fifo_init(struct usbhs_priv *priv); |
76 | void usbhs_fifo_quit(struct usbhs_priv *priv); | 76 | void usbhs_fifo_quit(struct usbhs_priv *priv); |
77 | 77 | ||
78 | /* | 78 | /* |
79 | * packet info | 79 | * packet info |
80 | */ | 80 | */ |
81 | extern struct usbhs_pkt_handle usbhs_fifo_pio_push_handler; | 81 | extern struct usbhs_pkt_handle usbhs_fifo_pio_push_handler; |
82 | extern struct usbhs_pkt_handle usbhs_fifo_pio_pop_handler; | 82 | extern struct usbhs_pkt_handle usbhs_fifo_pio_pop_handler; |
83 | extern struct usbhs_pkt_handle usbhs_ctrl_stage_end_handler; | 83 | extern struct usbhs_pkt_handle usbhs_ctrl_stage_end_handler; |
84 | 84 | ||
85 | extern struct usbhs_pkt_handle usbhs_fifo_dma_push_handler; | 85 | extern struct usbhs_pkt_handle usbhs_fifo_dma_push_handler; |
86 | extern struct usbhs_pkt_handle usbhs_fifo_dma_pop_handler; | 86 | extern struct usbhs_pkt_handle usbhs_fifo_dma_pop_handler; |
87 | 87 | ||
88 | extern struct usbhs_pkt_handle usbhs_dcp_status_stage_in_handler; | ||
89 | extern struct usbhs_pkt_handle usbhs_dcp_status_stage_out_handler; | ||
90 | |||
91 | extern struct usbhs_pkt_handle usbhs_dcp_data_stage_in_handler; | ||
92 | extern struct usbhs_pkt_handle usbhs_dcp_data_stage_out_handler; | ||
88 | 93 | ||
89 | void usbhs_pkt_init(struct usbhs_pkt *pkt); | 94 | void usbhs_pkt_init(struct usbhs_pkt *pkt); |
90 | void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt, | 95 | void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt, |
91 | void (*done)(struct usbhs_priv *priv, | 96 | void (*done)(struct usbhs_priv *priv, |
92 | struct usbhs_pkt *pkt), | 97 | struct usbhs_pkt *pkt), |
93 | void *buf, int len, int zero); | 98 | void *buf, int len, int zero); |
94 | struct usbhs_pkt *usbhs_pkt_pop(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt); | 99 | struct usbhs_pkt *usbhs_pkt_pop(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt); |
95 | void usbhs_pkt_start(struct usbhs_pipe *pipe); | 100 | void usbhs_pkt_start(struct usbhs_pipe *pipe); |
96 | 101 | ||
97 | #endif /* RENESAS_USB_FIFO_H */ | 102 | #endif /* RENESAS_USB_FIFO_H */ |
98 | 103 |