diff options
Diffstat (limited to 'drivers/usb/renesas_usbhs')
-rw-r--r-- | drivers/usb/renesas_usbhs/Kconfig | 13 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/Makefile | 2 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/common.c | 34 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/common.h | 44 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/fifo.c | 1016 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/fifo.h | 104 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/mod_gadget.c | 843 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/pipe.c | 298 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/pipe.h | 47 |
9 files changed, 1519 insertions, 882 deletions
diff --git a/drivers/usb/renesas_usbhs/Kconfig b/drivers/usb/renesas_usbhs/Kconfig index b2e64918884..286cbf1ca7d 100644 --- a/drivers/usb/renesas_usbhs/Kconfig +++ b/drivers/usb/renesas_usbhs/Kconfig | |||
@@ -1,5 +1,5 @@ | |||
1 | # | 1 | # |
2 | # Renesas USB Controller Drivers | 2 | # Renesas USBHS Controller Drivers |
3 | # | 3 | # |
4 | 4 | ||
5 | config USB_RENESAS_USBHS | 5 | config USB_RENESAS_USBHS |
@@ -7,10 +7,9 @@ config USB_RENESAS_USBHS | |||
7 | depends on SUPERH || ARCH_SHMOBILE | 7 | depends on SUPERH || ARCH_SHMOBILE |
8 | default n | 8 | default n |
9 | help | 9 | help |
10 | Renesas USBHS is a discrete USB host and peripheral controller chip | 10 | Renesas USBHS is a discrete USB host and peripheral controller chip |
11 | that supports both full and high speed USB 2.0 data transfers. | 11 | that supports both full and high speed USB 2.0 data transfers. |
12 | It has nine or more configurable endpoints, and endpoint zero. | 12 | It has nine or more configurable endpoints, and endpoint zero. |
13 | 13 | ||
14 | Say "y" to link the driver statically, or "m" to build a | 14 | Say "y" to link the driver statically, or "m" to build a |
15 | dynamically linked module called "renesas_usbhs" and force all | 15 | dynamically linked module called "renesas_usbhs" |
16 | gadget drivers to also be dynamically linked. | ||
diff --git a/drivers/usb/renesas_usbhs/Makefile b/drivers/usb/renesas_usbhs/Makefile index b8798ad1627..ce08345fa15 100644 --- a/drivers/usb/renesas_usbhs/Makefile +++ b/drivers/usb/renesas_usbhs/Makefile | |||
@@ -4,6 +4,6 @@ | |||
4 | 4 | ||
5 | obj-$(CONFIG_USB_RENESAS_USBHS) += renesas_usbhs.o | 5 | obj-$(CONFIG_USB_RENESAS_USBHS) += renesas_usbhs.o |
6 | 6 | ||
7 | renesas_usbhs-y := common.o mod.o pipe.o | 7 | renesas_usbhs-y := common.o mod.o pipe.o fifo.o |
8 | 8 | ||
9 | renesas_usbhs-$(CONFIG_USB_RENESAS_USBHS_UDC) += mod_gadget.o | 9 | renesas_usbhs-$(CONFIG_USB_RENESAS_USBHS_UDC) += mod_gadget.o |
diff --git a/drivers/usb/renesas_usbhs/common.c b/drivers/usb/renesas_usbhs/common.c index f3664d6af66..d8239e5efa6 100644 --- a/drivers/usb/renesas_usbhs/common.c +++ b/drivers/usb/renesas_usbhs/common.c | |||
@@ -21,6 +21,29 @@ | |||
21 | #include <linux/sysfs.h> | 21 | #include <linux/sysfs.h> |
22 | #include "./common.h" | 22 | #include "./common.h" |
23 | 23 | ||
24 | /* | ||
25 | * image of renesas_usbhs | ||
26 | * | ||
27 | * ex) gadget case | ||
28 | |||
29 | * mod.c | ||
30 | * mod_gadget.c | ||
31 | * mod_host.c pipe.c fifo.c | ||
32 | * | ||
33 | * +-------+ +-----------+ | ||
34 | * | pipe0 |------>| fifo pio | | ||
35 | * +------------+ +-------+ +-----------+ | ||
36 | * | mod_gadget |=====> | pipe1 |--+ | ||
37 | * +------------+ +-------+ | +-----------+ | ||
38 | * | pipe2 | | +-| fifo dma0 | | ||
39 | * +------------+ +-------+ | | +-----------+ | ||
40 | * | mod_host | | pipe3 |<-|--+ | ||
41 | * +------------+ +-------+ | +-----------+ | ||
42 | * | .... | +--->| fifo dma1 | | ||
43 | * | .... | +-----------+ | ||
44 | */ | ||
45 | |||
46 | |||
24 | #define USBHSF_RUNTIME_PWCTRL (1 << 0) | 47 | #define USBHSF_RUNTIME_PWCTRL (1 << 0) |
25 | 48 | ||
26 | /* status */ | 49 | /* status */ |
@@ -304,6 +327,8 @@ static int __devinit usbhs_probe(struct platform_device *pdev) | |||
304 | priv->dparam->pipe_type = usbhsc_default_pipe_type; | 327 | priv->dparam->pipe_type = usbhsc_default_pipe_type; |
305 | priv->dparam->pipe_size = ARRAY_SIZE(usbhsc_default_pipe_type); | 328 | priv->dparam->pipe_size = ARRAY_SIZE(usbhsc_default_pipe_type); |
306 | } | 329 | } |
330 | if (!priv->dparam->pio_dma_border) | ||
331 | priv->dparam->pio_dma_border = 64; /* 64byte */ | ||
307 | 332 | ||
308 | /* FIXME */ | 333 | /* FIXME */ |
309 | /* runtime power control ? */ | 334 | /* runtime power control ? */ |
@@ -323,10 +348,14 @@ static int __devinit usbhs_probe(struct platform_device *pdev) | |||
323 | if (ret < 0) | 348 | if (ret < 0) |
324 | goto probe_end_iounmap; | 349 | goto probe_end_iounmap; |
325 | 350 | ||
326 | ret = usbhs_mod_probe(priv); | 351 | ret = usbhs_fifo_probe(priv); |
327 | if (ret < 0) | 352 | if (ret < 0) |
328 | goto probe_end_pipe_exit; | 353 | goto probe_end_pipe_exit; |
329 | 354 | ||
355 | ret = usbhs_mod_probe(priv); | ||
356 | if (ret < 0) | ||
357 | goto probe_end_fifo_exit; | ||
358 | |||
330 | /* dev_set_drvdata should be called after usbhs_mod_init */ | 359 | /* dev_set_drvdata should be called after usbhs_mod_init */ |
331 | dev_set_drvdata(&pdev->dev, priv); | 360 | dev_set_drvdata(&pdev->dev, priv); |
332 | 361 | ||
@@ -374,6 +403,8 @@ probe_end_call_remove: | |||
374 | usbhs_platform_call(priv, hardware_exit, pdev); | 403 | usbhs_platform_call(priv, hardware_exit, pdev); |
375 | probe_end_mod_exit: | 404 | probe_end_mod_exit: |
376 | usbhs_mod_remove(priv); | 405 | usbhs_mod_remove(priv); |
406 | probe_end_fifo_exit: | ||
407 | usbhs_fifo_remove(priv); | ||
377 | probe_end_pipe_exit: | 408 | probe_end_pipe_exit: |
378 | usbhs_pipe_remove(priv); | 409 | usbhs_pipe_remove(priv); |
379 | probe_end_iounmap: | 410 | probe_end_iounmap: |
@@ -404,6 +435,7 @@ static int __devexit usbhs_remove(struct platform_device *pdev) | |||
404 | 435 | ||
405 | usbhs_platform_call(priv, hardware_exit, pdev); | 436 | usbhs_platform_call(priv, hardware_exit, pdev); |
406 | usbhs_mod_remove(priv); | 437 | usbhs_mod_remove(priv); |
438 | usbhs_fifo_remove(priv); | ||
407 | usbhs_pipe_remove(priv); | 439 | usbhs_pipe_remove(priv); |
408 | iounmap(priv->base); | 440 | iounmap(priv->base); |
409 | kfree(priv); | 441 | kfree(priv); |
diff --git a/drivers/usb/renesas_usbhs/common.h b/drivers/usb/renesas_usbhs/common.h index 0aadcb40276..b410463a121 100644 --- a/drivers/usb/renesas_usbhs/common.h +++ b/drivers/usb/renesas_usbhs/common.h | |||
@@ -36,6 +36,12 @@ struct usbhs_priv; | |||
36 | #define CFIFO 0x0014 | 36 | #define CFIFO 0x0014 |
37 | #define CFIFOSEL 0x0020 | 37 | #define CFIFOSEL 0x0020 |
38 | #define CFIFOCTR 0x0022 | 38 | #define CFIFOCTR 0x0022 |
39 | #define D0FIFO 0x0100 | ||
40 | #define D0FIFOSEL 0x0028 | ||
41 | #define D0FIFOCTR 0x002A | ||
42 | #define D1FIFO 0x0120 | ||
43 | #define D1FIFOSEL 0x002C | ||
44 | #define D1FIFOCTR 0x002E | ||
39 | #define INTENB0 0x0030 | 45 | #define INTENB0 0x0030 |
40 | #define INTENB1 0x0032 | 46 | #define INTENB1 0x0032 |
41 | #define BRDYENB 0x0036 | 47 | #define BRDYENB 0x0036 |
@@ -60,6 +66,30 @@ struct usbhs_priv; | |||
60 | #define PIPEMAXP 0x006C | 66 | #define PIPEMAXP 0x006C |
61 | #define PIPEPERI 0x006E | 67 | #define PIPEPERI 0x006E |
62 | #define PIPEnCTR 0x0070 | 68 | #define PIPEnCTR 0x0070 |
69 | #define PIPE1TRE 0x0090 | ||
70 | #define PIPE1TRN 0x0092 | ||
71 | #define PIPE2TRE 0x0094 | ||
72 | #define PIPE2TRN 0x0096 | ||
73 | #define PIPE3TRE 0x0098 | ||
74 | #define PIPE3TRN 0x009A | ||
75 | #define PIPE4TRE 0x009C | ||
76 | #define PIPE4TRN 0x009E | ||
77 | #define PIPE5TRE 0x00A0 | ||
78 | #define PIPE5TRN 0x00A2 | ||
79 | #define PIPEBTRE 0x00A4 | ||
80 | #define PIPEBTRN 0x00A6 | ||
81 | #define PIPECTRE 0x00A8 | ||
82 | #define PIPECTRN 0x00AA | ||
83 | #define PIPEDTRE 0x00AC | ||
84 | #define PIPEDTRN 0x00AE | ||
85 | #define PIPEETRE 0x00B0 | ||
86 | #define PIPEETRN 0x00B2 | ||
87 | #define PIPEFTRE 0x00B4 | ||
88 | #define PIPEFTRN 0x00B6 | ||
89 | #define PIPE9TRE 0x00B8 | ||
90 | #define PIPE9TRN 0x00BA | ||
91 | #define PIPEATRE 0x00BC | ||
92 | #define PIPEATRN 0x00BE | ||
63 | 93 | ||
64 | /* SYSCFG */ | 94 | /* SYSCFG */ |
65 | #define SCKE (1 << 10) /* USB Module Clock Enable */ | 95 | #define SCKE (1 << 10) /* USB Module Clock Enable */ |
@@ -78,6 +108,7 @@ struct usbhs_priv; | |||
78 | #define RHST_HIGH_SPEED 3 /* High-speed connection */ | 108 | #define RHST_HIGH_SPEED 3 /* High-speed connection */ |
79 | 109 | ||
80 | /* CFIFOSEL */ | 110 | /* CFIFOSEL */ |
111 | #define DREQE (1 << 12) /* DMA Transfer Request Enable */ | ||
81 | #define MBW_32 (0x2 << 10) /* CFIFO Port Access Bit Width */ | 112 | #define MBW_32 (0x2 << 10) /* CFIFO Port Access Bit Width */ |
82 | 113 | ||
83 | /* CFIFOCTR */ | 114 | /* CFIFOCTR */ |
@@ -164,6 +195,10 @@ struct usbhs_priv; | |||
164 | 195 | ||
165 | #define CCPL (1 << 2) /* Control Transfer End Enable */ | 196 | #define CCPL (1 << 2) /* Control Transfer End Enable */ |
166 | 197 | ||
198 | /* PIPEnTRE */ | ||
199 | #define TRENB (1 << 9) /* Transaction Counter Enable */ | ||
200 | #define TRCLR (1 << 8) /* Transaction Counter Clear */ | ||
201 | |||
167 | /* FRMNUM */ | 202 | /* FRMNUM */ |
168 | #define FRNM_MASK (0x7FF) | 203 | #define FRNM_MASK (0x7FF) |
169 | 204 | ||
@@ -194,6 +229,11 @@ struct usbhs_priv { | |||
194 | * pipe control | 229 | * pipe control |
195 | */ | 230 | */ |
196 | struct usbhs_pipe_info pipe_info; | 231 | struct usbhs_pipe_info pipe_info; |
232 | |||
233 | /* | ||
234 | * fifo control | ||
235 | */ | ||
236 | struct usbhs_fifo_info fifo_info; | ||
197 | }; | 237 | }; |
198 | 238 | ||
199 | /* | 239 | /* |
@@ -204,6 +244,10 @@ void usbhs_write(struct usbhs_priv *priv, u32 reg, u16 data); | |||
204 | void usbhs_bset(struct usbhs_priv *priv, u32 reg, u16 mask, u16 data); | 244 | void usbhs_bset(struct usbhs_priv *priv, u32 reg, u16 mask, u16 data); |
205 | 245 | ||
206 | int usbhsc_drvcllbck_notify_hotplug(struct platform_device *pdev); | 246 | int usbhsc_drvcllbck_notify_hotplug(struct platform_device *pdev); |
247 | |||
248 | #define usbhs_lock(p, f) spin_lock_irqsave(usbhs_priv_to_lock(p), f) | ||
249 | #define usbhs_unlock(p, f) spin_unlock_irqrestore(usbhs_priv_to_lock(p), f) | ||
250 | |||
207 | /* | 251 | /* |
208 | * sysconfig | 252 | * sysconfig |
209 | */ | 253 | */ |
diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c new file mode 100644 index 00000000000..a34430f55fb --- /dev/null +++ b/drivers/usb/renesas_usbhs/fifo.c | |||
@@ -0,0 +1,1016 @@ | |||
1 | /* | ||
2 | * Renesas USB driver | ||
3 | * | ||
4 | * Copyright (C) 2011 Renesas Solutions Corp. | ||
5 | * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
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 | ||
14 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
15 | * | ||
16 | */ | ||
17 | #include <linux/delay.h> | ||
18 | #include <linux/io.h> | ||
19 | #include <linux/scatterlist.h> | ||
20 | #include "./common.h" | ||
21 | #include "./pipe.h" | ||
22 | |||
23 | #define usbhsf_get_cfifo(p) (&((p)->fifo_info.cfifo)) | ||
24 | #define usbhsf_get_d0fifo(p) (&((p)->fifo_info.d0fifo)) | ||
25 | #define usbhsf_get_d1fifo(p) (&((p)->fifo_info.d1fifo)) | ||
26 | |||
27 | #define usbhsf_fifo_is_busy(f) ((f)->pipe) /* see usbhs_pipe_select_fifo */ | ||
28 | |||
29 | /* | ||
30 | * packet initialize | ||
31 | */ | ||
32 | void usbhs_pkt_init(struct usbhs_pkt *pkt) | ||
33 | { | ||
34 | pkt->dma = DMA_ADDR_INVALID; | ||
35 | INIT_LIST_HEAD(&pkt->node); | ||
36 | } | ||
37 | |||
38 | /* | ||
39 | * packet control function | ||
40 | */ | ||
41 | static int usbhsf_null_handle(struct usbhs_pkt *pkt, int *is_done) | ||
42 | { | ||
43 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pkt->pipe); | ||
44 | struct device *dev = usbhs_priv_to_dev(priv); | ||
45 | |||
46 | dev_err(dev, "null handler\n"); | ||
47 | |||
48 | return -EINVAL; | ||
49 | } | ||
50 | |||
51 | static struct usbhs_pkt_handle usbhsf_null_handler = { | ||
52 | .prepare = usbhsf_null_handle, | ||
53 | .try_run = usbhsf_null_handle, | ||
54 | }; | ||
55 | |||
56 | void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt, | ||
57 | struct usbhs_pkt_handle *handler, | ||
58 | void *buf, int len, int zero) | ||
59 | { | ||
60 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | ||
61 | struct device *dev = usbhs_priv_to_dev(priv); | ||
62 | unsigned long flags; | ||
63 | |||
64 | /******************** spin lock ********************/ | ||
65 | usbhs_lock(priv, flags); | ||
66 | |||
67 | if (!handler) { | ||
68 | dev_err(dev, "no handler function\n"); | ||
69 | handler = &usbhsf_null_handler; | ||
70 | } | ||
71 | |||
72 | list_del_init(&pkt->node); | ||
73 | list_add_tail(&pkt->node, &pipe->list); | ||
74 | |||
75 | pkt->pipe = pipe; | ||
76 | pkt->buf = buf; | ||
77 | pkt->handler = handler; | ||
78 | pkt->length = len; | ||
79 | pkt->zero = zero; | ||
80 | pkt->actual = 0; | ||
81 | |||
82 | usbhs_unlock(priv, flags); | ||
83 | /******************** spin unlock ******************/ | ||
84 | |||
85 | usbhs_pkt_start(pipe); | ||
86 | } | ||
87 | |||
88 | static void __usbhsf_pkt_del(struct usbhs_pkt *pkt) | ||
89 | { | ||
90 | list_del_init(&pkt->node); | ||
91 | } | ||
92 | |||
93 | static struct usbhs_pkt *__usbhsf_pkt_get(struct usbhs_pipe *pipe) | ||
94 | { | ||
95 | if (list_empty(&pipe->list)) | ||
96 | return NULL; | ||
97 | |||
98 | return list_entry(pipe->list.next, struct usbhs_pkt, node); | ||
99 | } | ||
100 | |||
101 | struct usbhs_pkt *usbhs_pkt_pop(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt) | ||
102 | { | ||
103 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | ||
104 | unsigned long flags; | ||
105 | |||
106 | /******************** spin lock ********************/ | ||
107 | usbhs_lock(priv, flags); | ||
108 | |||
109 | if (!pkt) | ||
110 | pkt = __usbhsf_pkt_get(pipe); | ||
111 | |||
112 | if (pkt) | ||
113 | __usbhsf_pkt_del(pkt); | ||
114 | |||
115 | usbhs_unlock(priv, flags); | ||
116 | /******************** spin unlock ******************/ | ||
117 | |||
118 | return pkt; | ||
119 | } | ||
120 | |||
121 | int __usbhs_pkt_handler(struct usbhs_pipe *pipe, int type) | ||
122 | { | ||
123 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | ||
124 | struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv); | ||
125 | struct usbhs_pkt *pkt; | ||
126 | struct device *dev = usbhs_priv_to_dev(priv); | ||
127 | int (*func)(struct usbhs_pkt *pkt, int *is_done); | ||
128 | unsigned long flags; | ||
129 | int ret = 0; | ||
130 | int is_done = 0; | ||
131 | |||
132 | /******************** spin lock ********************/ | ||
133 | usbhs_lock(priv, flags); | ||
134 | |||
135 | pkt = __usbhsf_pkt_get(pipe); | ||
136 | if (!pkt) | ||
137 | goto __usbhs_pkt_handler_end; | ||
138 | |||
139 | switch (type) { | ||
140 | case USBHSF_PKT_PREPARE: | ||
141 | func = pkt->handler->prepare; | ||
142 | break; | ||
143 | case USBHSF_PKT_TRY_RUN: | ||
144 | func = pkt->handler->try_run; | ||
145 | break; | ||
146 | case USBHSF_PKT_DMA_DONE: | ||
147 | func = pkt->handler->dma_done; | ||
148 | break; | ||
149 | default: | ||
150 | dev_err(dev, "unknown pkt hander\n"); | ||
151 | goto __usbhs_pkt_handler_end; | ||
152 | } | ||
153 | |||
154 | ret = func(pkt, &is_done); | ||
155 | |||
156 | if (is_done) | ||
157 | __usbhsf_pkt_del(pkt); | ||
158 | |||
159 | __usbhs_pkt_handler_end: | ||
160 | usbhs_unlock(priv, flags); | ||
161 | /******************** spin unlock ******************/ | ||
162 | |||
163 | if (is_done) { | ||
164 | info->done(pkt); | ||
165 | usbhs_pkt_start(pipe); | ||
166 | } | ||
167 | |||
168 | return ret; | ||
169 | } | ||
170 | |||
171 | /* | ||
172 | * irq enable/disable function | ||
173 | */ | ||
174 | #define usbhsf_irq_empty_ctrl(p, e) usbhsf_irq_callback_ctrl(p, bempsts, e) | ||
175 | #define usbhsf_irq_ready_ctrl(p, e) usbhsf_irq_callback_ctrl(p, brdysts, e) | ||
176 | #define usbhsf_irq_callback_ctrl(pipe, status, enable) \ | ||
177 | ({ \ | ||
178 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); \ | ||
179 | struct usbhs_mod *mod = usbhs_mod_get_current(priv); \ | ||
180 | u16 status = (1 << usbhs_pipe_number(pipe)); \ | ||
181 | if (!mod) \ | ||
182 | return; \ | ||
183 | if (enable) \ | ||
184 | mod->irq_##status |= status; \ | ||
185 | else \ | ||
186 | mod->irq_##status &= ~status; \ | ||
187 | usbhs_irq_callback_update(priv, mod); \ | ||
188 | }) | ||
189 | |||
190 | static void usbhsf_tx_irq_ctrl(struct usbhs_pipe *pipe, int enable) | ||
191 | { | ||
192 | /* | ||
193 | * And DCP pipe can NOT use "ready interrupt" for "send" | ||
194 | * it should use "empty" interrupt. | ||
195 | * see | ||
196 | * "Operation" - "Interrupt Function" - "BRDY Interrupt" | ||
197 | * | ||
198 | * on the other hand, normal pipe can use "ready interrupt" for "send" | ||
199 | * even though it is single/double buffer | ||
200 | */ | ||
201 | if (usbhs_pipe_is_dcp(pipe)) | ||
202 | usbhsf_irq_empty_ctrl(pipe, enable); | ||
203 | else | ||
204 | usbhsf_irq_ready_ctrl(pipe, enable); | ||
205 | } | ||
206 | |||
207 | static void usbhsf_rx_irq_ctrl(struct usbhs_pipe *pipe, int enable) | ||
208 | { | ||
209 | usbhsf_irq_ready_ctrl(pipe, enable); | ||
210 | } | ||
211 | |||
212 | /* | ||
213 | * FIFO ctrl | ||
214 | */ | ||
215 | static void usbhsf_send_terminator(struct usbhs_pipe *pipe, | ||
216 | struct usbhs_fifo *fifo) | ||
217 | { | ||
218 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | ||
219 | |||
220 | usbhs_bset(priv, fifo->ctr, BVAL, BVAL); | ||
221 | } | ||
222 | |||
223 | static int usbhsf_fifo_barrier(struct usbhs_priv *priv, | ||
224 | struct usbhs_fifo *fifo) | ||
225 | { | ||
226 | int timeout = 1024; | ||
227 | |||
228 | do { | ||
229 | /* The FIFO port is accessible */ | ||
230 | if (usbhs_read(priv, fifo->ctr) & FRDY) | ||
231 | return 0; | ||
232 | |||
233 | udelay(10); | ||
234 | } while (timeout--); | ||
235 | |||
236 | return -EBUSY; | ||
237 | } | ||
238 | |||
239 | static void usbhsf_fifo_clear(struct usbhs_pipe *pipe, | ||
240 | struct usbhs_fifo *fifo) | ||
241 | { | ||
242 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | ||
243 | |||
244 | if (!usbhs_pipe_is_dcp(pipe)) | ||
245 | usbhsf_fifo_barrier(priv, fifo); | ||
246 | |||
247 | usbhs_write(priv, fifo->ctr, BCLR); | ||
248 | } | ||
249 | |||
250 | static int usbhsf_fifo_rcv_len(struct usbhs_priv *priv, | ||
251 | struct usbhs_fifo *fifo) | ||
252 | { | ||
253 | return usbhs_read(priv, fifo->ctr) & DTLN_MASK; | ||
254 | } | ||
255 | |||
256 | static void usbhsf_fifo_unselect(struct usbhs_pipe *pipe, | ||
257 | struct usbhs_fifo *fifo) | ||
258 | { | ||
259 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | ||
260 | |||
261 | usbhs_pipe_select_fifo(pipe, NULL); | ||
262 | usbhs_write(priv, fifo->sel, 0); | ||
263 | } | ||
264 | |||
265 | static int usbhsf_fifo_select(struct usbhs_pipe *pipe, | ||
266 | struct usbhs_fifo *fifo, | ||
267 | int write) | ||
268 | { | ||
269 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | ||
270 | struct device *dev = usbhs_priv_to_dev(priv); | ||
271 | int timeout = 1024; | ||
272 | u16 mask = ((1 << 5) | 0xF); /* mask of ISEL | CURPIPE */ | ||
273 | u16 base = usbhs_pipe_number(pipe); /* CURPIPE */ | ||
274 | |||
275 | if (usbhs_pipe_is_busy(pipe) || | ||
276 | usbhsf_fifo_is_busy(fifo)) | ||
277 | return -EBUSY; | ||
278 | |||
279 | if (usbhs_pipe_is_dcp(pipe)) | ||
280 | base |= (1 == write) << 5; /* ISEL */ | ||
281 | |||
282 | /* "base" will be used below */ | ||
283 | usbhs_write(priv, fifo->sel, base | MBW_32); | ||
284 | |||
285 | /* check ISEL and CURPIPE value */ | ||
286 | while (timeout--) { | ||
287 | if (base == (mask & usbhs_read(priv, fifo->sel))) { | ||
288 | usbhs_pipe_select_fifo(pipe, fifo); | ||
289 | return 0; | ||
290 | } | ||
291 | udelay(10); | ||
292 | } | ||
293 | |||
294 | dev_err(dev, "fifo select error\n"); | ||
295 | |||
296 | return -EIO; | ||
297 | } | ||
298 | |||
299 | /* | ||
300 | * PIO push handler | ||
301 | */ | ||
302 | static int usbhsf_pio_try_push(struct usbhs_pkt *pkt, int *is_done) | ||
303 | { | ||
304 | struct usbhs_pipe *pipe = pkt->pipe; | ||
305 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | ||
306 | struct device *dev = usbhs_priv_to_dev(priv); | ||
307 | struct usbhs_fifo *fifo = usbhsf_get_cfifo(priv); /* CFIFO */ | ||
308 | void __iomem *addr = priv->base + fifo->port; | ||
309 | u8 *buf; | ||
310 | int maxp = usbhs_pipe_get_maxpacket(pipe); | ||
311 | int total_len; | ||
312 | int i, ret, len; | ||
313 | int is_short; | ||
314 | |||
315 | ret = usbhsf_fifo_select(pipe, fifo, 1); | ||
316 | if (ret < 0) | ||
317 | return 0; | ||
318 | |||
319 | ret = usbhs_pipe_is_accessible(pipe); | ||
320 | if (ret < 0) { | ||
321 | /* inaccessible pipe is not an error */ | ||
322 | ret = 0; | ||
323 | goto usbhs_fifo_write_busy; | ||
324 | } | ||
325 | |||
326 | ret = usbhsf_fifo_barrier(priv, fifo); | ||
327 | if (ret < 0) | ||
328 | goto usbhs_fifo_write_busy; | ||
329 | |||
330 | buf = pkt->buf + pkt->actual; | ||
331 | len = pkt->length - pkt->actual; | ||
332 | len = min(len, maxp); | ||
333 | total_len = len; | ||
334 | is_short = total_len < maxp; | ||
335 | |||
336 | /* | ||
337 | * FIXME | ||
338 | * | ||
339 | * 32-bit access only | ||
340 | */ | ||
341 | if (len >= 4 && !((unsigned long)buf & 0x03)) { | ||
342 | iowrite32_rep(addr, buf, len / 4); | ||
343 | len %= 4; | ||
344 | buf += total_len - len; | ||
345 | } | ||
346 | |||
347 | /* the rest operation */ | ||
348 | for (i = 0; i < len; i++) | ||
349 | iowrite8(buf[i], addr + (0x03 - (i & 0x03))); | ||
350 | |||
351 | /* | ||
352 | * variable update | ||
353 | */ | ||
354 | pkt->actual += total_len; | ||
355 | |||
356 | if (pkt->actual < pkt->length) | ||
357 | *is_done = 0; /* there are remainder data */ | ||
358 | else if (is_short) | ||
359 | *is_done = 1; /* short packet */ | ||
360 | else | ||
361 | *is_done = !pkt->zero; /* send zero packet ? */ | ||
362 | |||
363 | /* | ||
364 | * pipe/irq handling | ||
365 | */ | ||
366 | if (is_short) | ||
367 | usbhsf_send_terminator(pipe, fifo); | ||
368 | |||
369 | usbhsf_tx_irq_ctrl(pipe, !*is_done); | ||
370 | usbhs_pipe_enable(pipe); | ||
371 | |||
372 | dev_dbg(dev, " send %d (%d/ %d/ %d/ %d)\n", | ||
373 | usbhs_pipe_number(pipe), | ||
374 | pkt->length, pkt->actual, *is_done, pkt->zero); | ||
375 | |||
376 | /* | ||
377 | * Transmission end | ||
378 | */ | ||
379 | if (*is_done) { | ||
380 | if (usbhs_pipe_is_dcp(pipe)) | ||
381 | usbhs_dcp_control_transfer_done(pipe); | ||
382 | } | ||
383 | |||
384 | usbhsf_fifo_unselect(pipe, fifo); | ||
385 | |||
386 | return 0; | ||
387 | |||
388 | usbhs_fifo_write_busy: | ||
389 | usbhsf_fifo_unselect(pipe, fifo); | ||
390 | |||
391 | /* | ||
392 | * pipe is busy. | ||
393 | * retry in interrupt | ||
394 | */ | ||
395 | usbhsf_tx_irq_ctrl(pipe, 1); | ||
396 | |||
397 | return ret; | ||
398 | } | ||
399 | |||
400 | struct usbhs_pkt_handle usbhs_fifo_pio_push_handler = { | ||
401 | .prepare = usbhsf_pio_try_push, | ||
402 | .try_run = usbhsf_pio_try_push, | ||
403 | }; | ||
404 | |||
405 | /* | ||
406 | * PIO pop handler | ||
407 | */ | ||
408 | static int usbhsf_prepare_pop(struct usbhs_pkt *pkt, int *is_done) | ||
409 | { | ||
410 | struct usbhs_pipe *pipe = pkt->pipe; | ||
411 | |||
412 | if (usbhs_pipe_is_busy(pipe)) | ||
413 | return 0; | ||
414 | |||
415 | /* | ||
416 | * pipe enable to prepare packet receive | ||
417 | */ | ||
418 | |||
419 | usbhs_pipe_enable(pipe); | ||
420 | usbhsf_rx_irq_ctrl(pipe, 1); | ||
421 | |||
422 | return 0; | ||
423 | } | ||
424 | |||
425 | static int usbhsf_pio_try_pop(struct usbhs_pkt *pkt, int *is_done) | ||
426 | { | ||
427 | struct usbhs_pipe *pipe = pkt->pipe; | ||
428 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | ||
429 | struct device *dev = usbhs_priv_to_dev(priv); | ||
430 | struct usbhs_fifo *fifo = usbhsf_get_cfifo(priv); /* CFIFO */ | ||
431 | void __iomem *addr = priv->base + fifo->port; | ||
432 | u8 *buf; | ||
433 | u32 data = 0; | ||
434 | int maxp = usbhs_pipe_get_maxpacket(pipe); | ||
435 | int rcv_len, len; | ||
436 | int i, ret; | ||
437 | int total_len = 0; | ||
438 | |||
439 | ret = usbhsf_fifo_select(pipe, fifo, 0); | ||
440 | if (ret < 0) | ||
441 | return 0; | ||
442 | |||
443 | ret = usbhsf_fifo_barrier(priv, fifo); | ||
444 | if (ret < 0) | ||
445 | goto usbhs_fifo_read_busy; | ||
446 | |||
447 | rcv_len = usbhsf_fifo_rcv_len(priv, fifo); | ||
448 | |||
449 | buf = pkt->buf + pkt->actual; | ||
450 | len = pkt->length - pkt->actual; | ||
451 | len = min(len, rcv_len); | ||
452 | total_len = len; | ||
453 | |||
454 | /* | ||
455 | * Buffer clear if Zero-Length packet | ||
456 | * | ||
457 | * see | ||
458 | * "Operation" - "FIFO Buffer Memory" - "FIFO Port Function" | ||
459 | */ | ||
460 | if (0 == rcv_len) { | ||
461 | usbhsf_fifo_clear(pipe, fifo); | ||
462 | goto usbhs_fifo_read_end; | ||
463 | } | ||
464 | |||
465 | /* | ||
466 | * FIXME | ||
467 | * | ||
468 | * 32-bit access only | ||
469 | */ | ||
470 | if (len >= 4 && !((unsigned long)buf & 0x03)) { | ||
471 | ioread32_rep(addr, buf, len / 4); | ||
472 | len %= 4; | ||
473 | buf += total_len - len; | ||
474 | } | ||
475 | |||
476 | /* the rest operation */ | ||
477 | for (i = 0; i < len; i++) { | ||
478 | if (!(i & 0x03)) | ||
479 | data = ioread32(addr); | ||
480 | |||
481 | buf[i] = (data >> ((i & 0x03) * 8)) & 0xff; | ||
482 | } | ||
483 | |||
484 | pkt->actual += total_len; | ||
485 | |||
486 | usbhs_fifo_read_end: | ||
487 | if ((pkt->actual == pkt->length) || /* receive all data */ | ||
488 | (total_len < maxp)) { /* short packet */ | ||
489 | *is_done = 1; | ||
490 | usbhsf_rx_irq_ctrl(pipe, 0); | ||
491 | usbhs_pipe_disable(pipe); | ||
492 | } | ||
493 | |||
494 | dev_dbg(dev, " recv %d (%d/ %d/ %d/ %d)\n", | ||
495 | usbhs_pipe_number(pipe), | ||
496 | pkt->length, pkt->actual, *is_done, pkt->zero); | ||
497 | |||
498 | usbhs_fifo_read_busy: | ||
499 | usbhsf_fifo_unselect(pipe, fifo); | ||
500 | |||
501 | return ret; | ||
502 | } | ||
503 | |||
504 | struct usbhs_pkt_handle usbhs_fifo_pio_pop_handler = { | ||
505 | .prepare = usbhsf_prepare_pop, | ||
506 | .try_run = usbhsf_pio_try_pop, | ||
507 | }; | ||
508 | |||
509 | /* | ||
510 | * DCP ctrol statge handler | ||
511 | */ | ||
512 | static int usbhsf_ctrl_stage_end(struct usbhs_pkt *pkt, int *is_done) | ||
513 | { | ||
514 | usbhs_dcp_control_transfer_done(pkt->pipe); | ||
515 | |||
516 | *is_done = 1; | ||
517 | |||
518 | return 0; | ||
519 | } | ||
520 | |||
521 | struct usbhs_pkt_handle usbhs_ctrl_stage_end_handler = { | ||
522 | .prepare = usbhsf_ctrl_stage_end, | ||
523 | .try_run = usbhsf_ctrl_stage_end, | ||
524 | }; | ||
525 | |||
526 | /* | ||
527 | * DMA fifo functions | ||
528 | */ | ||
529 | static struct dma_chan *usbhsf_dma_chan_get(struct usbhs_fifo *fifo, | ||
530 | struct usbhs_pkt *pkt) | ||
531 | { | ||
532 | if (&usbhs_fifo_dma_push_handler == pkt->handler) | ||
533 | return fifo->tx_chan; | ||
534 | |||
535 | if (&usbhs_fifo_dma_pop_handler == pkt->handler) | ||
536 | return fifo->rx_chan; | ||
537 | |||
538 | return NULL; | ||
539 | } | ||
540 | |||
541 | static struct usbhs_fifo *usbhsf_get_dma_fifo(struct usbhs_priv *priv, | ||
542 | struct usbhs_pkt *pkt) | ||
543 | { | ||
544 | struct usbhs_fifo *fifo; | ||
545 | |||
546 | /* DMA :: D0FIFO */ | ||
547 | fifo = usbhsf_get_d0fifo(priv); | ||
548 | if (usbhsf_dma_chan_get(fifo, pkt) && | ||
549 | !usbhsf_fifo_is_busy(fifo)) | ||
550 | return fifo; | ||
551 | |||
552 | /* DMA :: D1FIFO */ | ||
553 | fifo = usbhsf_get_d1fifo(priv); | ||
554 | if (usbhsf_dma_chan_get(fifo, pkt) && | ||
555 | !usbhsf_fifo_is_busy(fifo)) | ||
556 | return fifo; | ||
557 | |||
558 | return NULL; | ||
559 | } | ||
560 | |||
561 | #define usbhsf_dma_start(p, f) __usbhsf_dma_ctrl(p, f, DREQE) | ||
562 | #define usbhsf_dma_stop(p, f) __usbhsf_dma_ctrl(p, f, 0) | ||
563 | static void __usbhsf_dma_ctrl(struct usbhs_pipe *pipe, | ||
564 | struct usbhs_fifo *fifo, | ||
565 | u16 dreqe) | ||
566 | { | ||
567 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | ||
568 | |||
569 | usbhs_bset(priv, fifo->sel, DREQE, dreqe); | ||
570 | } | ||
571 | |||
572 | #define usbhsf_dma_map(p) __usbhsf_dma_map_ctrl(p, 1) | ||
573 | #define usbhsf_dma_unmap(p) __usbhsf_dma_map_ctrl(p, 0) | ||
574 | static int __usbhsf_dma_map_ctrl(struct usbhs_pkt *pkt, int map) | ||
575 | { | ||
576 | struct usbhs_pipe *pipe = pkt->pipe; | ||
577 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | ||
578 | struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv); | ||
579 | |||
580 | return info->dma_map_ctrl(pkt, map); | ||
581 | } | ||
582 | |||
583 | static void usbhsf_dma_complete(void *arg); | ||
584 | static void usbhsf_dma_prepare_tasklet(unsigned long data) | ||
585 | { | ||
586 | struct usbhs_pkt *pkt = (struct usbhs_pkt *)data; | ||
587 | struct usbhs_pipe *pipe = pkt->pipe; | ||
588 | struct usbhs_fifo *fifo = usbhs_pipe_to_fifo(pipe); | ||
589 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | ||
590 | struct scatterlist sg; | ||
591 | struct dma_async_tx_descriptor *desc; | ||
592 | struct dma_chan *chan = usbhsf_dma_chan_get(fifo, pkt); | ||
593 | struct device *dev = usbhs_priv_to_dev(priv); | ||
594 | enum dma_data_direction dir; | ||
595 | dma_cookie_t cookie; | ||
596 | |||
597 | dir = usbhs_pipe_is_dir_in(pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE; | ||
598 | |||
599 | sg_init_table(&sg, 1); | ||
600 | sg_set_page(&sg, virt_to_page(pkt->dma), | ||
601 | pkt->length, offset_in_page(pkt->dma)); | ||
602 | sg_dma_address(&sg) = pkt->dma + pkt->actual; | ||
603 | sg_dma_len(&sg) = pkt->trans; | ||
604 | |||
605 | desc = chan->device->device_prep_slave_sg(chan, &sg, 1, dir, | ||
606 | DMA_PREP_INTERRUPT | | ||
607 | DMA_CTRL_ACK); | ||
608 | if (!desc) | ||
609 | return; | ||
610 | |||
611 | desc->callback = usbhsf_dma_complete; | ||
612 | desc->callback_param = pipe; | ||
613 | |||
614 | cookie = desc->tx_submit(desc); | ||
615 | if (cookie < 0) { | ||
616 | dev_err(dev, "Failed to submit dma descriptor\n"); | ||
617 | return; | ||
618 | } | ||
619 | |||
620 | dev_dbg(dev, " %s %d (%d/ %d)\n", | ||
621 | fifo->name, usbhs_pipe_number(pipe), pkt->length, pkt->zero); | ||
622 | |||
623 | usbhsf_dma_start(pipe, fifo); | ||
624 | dma_async_issue_pending(chan); | ||
625 | } | ||
626 | |||
627 | /* | ||
628 | * DMA push handler | ||
629 | */ | ||
630 | static int usbhsf_dma_prepare_push(struct usbhs_pkt *pkt, int *is_done) | ||
631 | { | ||
632 | struct usbhs_pipe *pipe = pkt->pipe; | ||
633 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | ||
634 | struct usbhs_fifo *fifo; | ||
635 | int len = pkt->length - pkt->actual; | ||
636 | int ret; | ||
637 | |||
638 | if (usbhs_pipe_is_busy(pipe)) | ||
639 | return 0; | ||
640 | |||
641 | /* use PIO if packet is less than pio_dma_border or pipe is DCP */ | ||
642 | if ((len < usbhs_get_dparam(priv, pio_dma_border)) || | ||
643 | usbhs_pipe_is_dcp(pipe)) | ||
644 | goto usbhsf_pio_prepare_push; | ||
645 | |||
646 | if (len % 4) /* 32bit alignment */ | ||
647 | goto usbhsf_pio_prepare_push; | ||
648 | |||
649 | if (((u32)pkt->buf + pkt->actual) & 0x7) /* 8byte alignment */ | ||
650 | goto usbhsf_pio_prepare_push; | ||
651 | |||
652 | /* get enable DMA fifo */ | ||
653 | fifo = usbhsf_get_dma_fifo(priv, pkt); | ||
654 | if (!fifo) | ||
655 | goto usbhsf_pio_prepare_push; | ||
656 | |||
657 | if (usbhsf_dma_map(pkt) < 0) | ||
658 | goto usbhsf_pio_prepare_push; | ||
659 | |||
660 | ret = usbhsf_fifo_select(pipe, fifo, 0); | ||
661 | if (ret < 0) | ||
662 | goto usbhsf_pio_prepare_push_unmap; | ||
663 | |||
664 | pkt->trans = len; | ||
665 | |||
666 | tasklet_init(&fifo->tasklet, | ||
667 | usbhsf_dma_prepare_tasklet, | ||
668 | (unsigned long)pkt); | ||
669 | |||
670 | tasklet_schedule(&fifo->tasklet); | ||
671 | |||
672 | return 0; | ||
673 | |||
674 | usbhsf_pio_prepare_push_unmap: | ||
675 | usbhsf_dma_unmap(pkt); | ||
676 | usbhsf_pio_prepare_push: | ||
677 | /* | ||
678 | * change handler to PIO | ||
679 | */ | ||
680 | pkt->handler = &usbhs_fifo_pio_push_handler; | ||
681 | |||
682 | return pkt->handler->prepare(pkt, is_done); | ||
683 | } | ||
684 | |||
685 | static int usbhsf_dma_push_done(struct usbhs_pkt *pkt, int *is_done) | ||
686 | { | ||
687 | struct usbhs_pipe *pipe = pkt->pipe; | ||
688 | |||
689 | pkt->actual = pkt->trans; | ||
690 | |||
691 | *is_done = !pkt->zero; /* send zero packet ? */ | ||
692 | |||
693 | usbhsf_dma_stop(pipe, pipe->fifo); | ||
694 | usbhsf_dma_unmap(pkt); | ||
695 | usbhsf_fifo_unselect(pipe, pipe->fifo); | ||
696 | |||
697 | return 0; | ||
698 | } | ||
699 | |||
700 | struct usbhs_pkt_handle usbhs_fifo_dma_push_handler = { | ||
701 | .prepare = usbhsf_dma_prepare_push, | ||
702 | .dma_done = usbhsf_dma_push_done, | ||
703 | }; | ||
704 | |||
705 | /* | ||
706 | * DMA pop handler | ||
707 | */ | ||
708 | static int usbhsf_dma_try_pop(struct usbhs_pkt *pkt, int *is_done) | ||
709 | { | ||
710 | struct usbhs_pipe *pipe = pkt->pipe; | ||
711 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | ||
712 | struct usbhs_fifo *fifo; | ||
713 | int len, ret; | ||
714 | |||
715 | if (usbhs_pipe_is_busy(pipe)) | ||
716 | return 0; | ||
717 | |||
718 | if (usbhs_pipe_is_dcp(pipe)) | ||
719 | goto usbhsf_pio_prepare_pop; | ||
720 | |||
721 | /* get enable DMA fifo */ | ||
722 | fifo = usbhsf_get_dma_fifo(priv, pkt); | ||
723 | if (!fifo) | ||
724 | goto usbhsf_pio_prepare_pop; | ||
725 | |||
726 | if (((u32)pkt->buf + pkt->actual) & 0x7) /* 8byte alignment */ | ||
727 | goto usbhsf_pio_prepare_pop; | ||
728 | |||
729 | ret = usbhsf_fifo_select(pipe, fifo, 0); | ||
730 | if (ret < 0) | ||
731 | goto usbhsf_pio_prepare_pop; | ||
732 | |||
733 | /* use PIO if packet is less than pio_dma_border */ | ||
734 | len = usbhsf_fifo_rcv_len(priv, fifo); | ||
735 | len = min(pkt->length - pkt->actual, len); | ||
736 | if (len % 4) /* 32bit alignment */ | ||
737 | goto usbhsf_pio_prepare_pop_unselect; | ||
738 | |||
739 | if (len < usbhs_get_dparam(priv, pio_dma_border)) | ||
740 | goto usbhsf_pio_prepare_pop_unselect; | ||
741 | |||
742 | ret = usbhsf_fifo_barrier(priv, fifo); | ||
743 | if (ret < 0) | ||
744 | goto usbhsf_pio_prepare_pop_unselect; | ||
745 | |||
746 | if (usbhsf_dma_map(pkt) < 0) | ||
747 | goto usbhsf_pio_prepare_pop_unselect; | ||
748 | |||
749 | /* DMA */ | ||
750 | |||
751 | /* | ||
752 | * usbhs_fifo_dma_pop_handler :: prepare | ||
753 | * enabled irq to come here. | ||
754 | * but it is no longer needed for DMA. disable it. | ||
755 | */ | ||
756 | usbhsf_rx_irq_ctrl(pipe, 0); | ||
757 | |||
758 | pkt->trans = len; | ||
759 | |||
760 | tasklet_init(&fifo->tasklet, | ||
761 | usbhsf_dma_prepare_tasklet, | ||
762 | (unsigned long)pkt); | ||
763 | |||
764 | tasklet_schedule(&fifo->tasklet); | ||
765 | |||
766 | return 0; | ||
767 | |||
768 | usbhsf_pio_prepare_pop_unselect: | ||
769 | usbhsf_fifo_unselect(pipe, fifo); | ||
770 | usbhsf_pio_prepare_pop: | ||
771 | |||
772 | /* | ||
773 | * change handler to PIO | ||
774 | */ | ||
775 | pkt->handler = &usbhs_fifo_pio_pop_handler; | ||
776 | |||
777 | return pkt->handler->try_run(pkt, is_done); | ||
778 | } | ||
779 | |||
780 | static int usbhsf_dma_pop_done(struct usbhs_pkt *pkt, int *is_done) | ||
781 | { | ||
782 | struct usbhs_pipe *pipe = pkt->pipe; | ||
783 | int maxp = usbhs_pipe_get_maxpacket(pipe); | ||
784 | |||
785 | usbhsf_dma_stop(pipe, pipe->fifo); | ||
786 | usbhsf_dma_unmap(pkt); | ||
787 | usbhsf_fifo_unselect(pipe, pipe->fifo); | ||
788 | |||
789 | pkt->actual += pkt->trans; | ||
790 | |||
791 | if ((pkt->actual == pkt->length) || /* receive all data */ | ||
792 | (pkt->trans < maxp)) { /* short packet */ | ||
793 | *is_done = 1; | ||
794 | } else { | ||
795 | /* re-enable */ | ||
796 | usbhsf_prepare_pop(pkt, is_done); | ||
797 | } | ||
798 | |||
799 | return 0; | ||
800 | } | ||
801 | |||
802 | struct usbhs_pkt_handle usbhs_fifo_dma_pop_handler = { | ||
803 | .prepare = usbhsf_prepare_pop, | ||
804 | .try_run = usbhsf_dma_try_pop, | ||
805 | .dma_done = usbhsf_dma_pop_done | ||
806 | }; | ||
807 | |||
808 | /* | ||
809 | * DMA setting | ||
810 | */ | ||
811 | static bool usbhsf_dma_filter(struct dma_chan *chan, void *param) | ||
812 | { | ||
813 | struct sh_dmae_slave *slave = param; | ||
814 | |||
815 | /* | ||
816 | * FIXME | ||
817 | * | ||
818 | * usbhs doesn't recognize id = 0 as valid DMA | ||
819 | */ | ||
820 | if (0 == slave->slave_id) | ||
821 | return false; | ||
822 | |||
823 | chan->private = slave; | ||
824 | |||
825 | return true; | ||
826 | } | ||
827 | |||
828 | static void usbhsf_dma_quit(struct usbhs_priv *priv, struct usbhs_fifo *fifo) | ||
829 | { | ||
830 | if (fifo->tx_chan) | ||
831 | dma_release_channel(fifo->tx_chan); | ||
832 | if (fifo->rx_chan) | ||
833 | dma_release_channel(fifo->rx_chan); | ||
834 | |||
835 | fifo->tx_chan = NULL; | ||
836 | fifo->rx_chan = NULL; | ||
837 | } | ||
838 | |||
839 | static void usbhsf_dma_init(struct usbhs_priv *priv, | ||
840 | struct usbhs_fifo *fifo) | ||
841 | { | ||
842 | struct device *dev = usbhs_priv_to_dev(priv); | ||
843 | dma_cap_mask_t mask; | ||
844 | |||
845 | dma_cap_zero(mask); | ||
846 | dma_cap_set(DMA_SLAVE, mask); | ||
847 | fifo->tx_chan = dma_request_channel(mask, usbhsf_dma_filter, | ||
848 | &fifo->tx_slave); | ||
849 | |||
850 | dma_cap_zero(mask); | ||
851 | dma_cap_set(DMA_SLAVE, mask); | ||
852 | fifo->rx_chan = dma_request_channel(mask, usbhsf_dma_filter, | ||
853 | &fifo->rx_slave); | ||
854 | |||
855 | if (fifo->tx_chan || fifo->rx_chan) | ||
856 | dev_dbg(dev, "enable DMAEngine (%s%s%s)\n", | ||
857 | fifo->name, | ||
858 | fifo->tx_chan ? "[TX]" : " ", | ||
859 | fifo->rx_chan ? "[RX]" : " "); | ||
860 | } | ||
861 | |||
862 | /* | ||
863 | * irq functions | ||
864 | */ | ||
865 | static int usbhsf_irq_empty(struct usbhs_priv *priv, | ||
866 | struct usbhs_irq_state *irq_state) | ||
867 | { | ||
868 | struct usbhs_pipe *pipe; | ||
869 | struct device *dev = usbhs_priv_to_dev(priv); | ||
870 | int i, ret; | ||
871 | |||
872 | if (!irq_state->bempsts) { | ||
873 | dev_err(dev, "debug %s !!\n", __func__); | ||
874 | return -EIO; | ||
875 | } | ||
876 | |||
877 | dev_dbg(dev, "irq empty [0x%04x]\n", irq_state->bempsts); | ||
878 | |||
879 | /* | ||
880 | * search interrupted "pipe" | ||
881 | * not "uep". | ||
882 | */ | ||
883 | usbhs_for_each_pipe_with_dcp(pipe, priv, i) { | ||
884 | if (!(irq_state->bempsts & (1 << i))) | ||
885 | continue; | ||
886 | |||
887 | ret = usbhs_pkt_run(pipe); | ||
888 | if (ret < 0) | ||
889 | dev_err(dev, "irq_empty run_error %d : %d\n", i, ret); | ||
890 | } | ||
891 | |||
892 | return 0; | ||
893 | } | ||
894 | |||
895 | static int usbhsf_irq_ready(struct usbhs_priv *priv, | ||
896 | struct usbhs_irq_state *irq_state) | ||
897 | { | ||
898 | struct usbhs_pipe *pipe; | ||
899 | struct device *dev = usbhs_priv_to_dev(priv); | ||
900 | int i, ret; | ||
901 | |||
902 | if (!irq_state->brdysts) { | ||
903 | dev_err(dev, "debug %s !!\n", __func__); | ||
904 | return -EIO; | ||
905 | } | ||
906 | |||
907 | dev_dbg(dev, "irq ready [0x%04x]\n", irq_state->brdysts); | ||
908 | |||
909 | /* | ||
910 | * search interrupted "pipe" | ||
911 | * not "uep". | ||
912 | */ | ||
913 | usbhs_for_each_pipe_with_dcp(pipe, priv, i) { | ||
914 | if (!(irq_state->brdysts & (1 << i))) | ||
915 | continue; | ||
916 | |||
917 | ret = usbhs_pkt_run(pipe); | ||
918 | if (ret < 0) | ||
919 | dev_err(dev, "irq_ready run_error %d : %d\n", i, ret); | ||
920 | } | ||
921 | |||
922 | return 0; | ||
923 | } | ||
924 | |||
925 | static void usbhsf_dma_complete(void *arg) | ||
926 | { | ||
927 | struct usbhs_pipe *pipe = arg; | ||
928 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | ||
929 | struct device *dev = usbhs_priv_to_dev(priv); | ||
930 | int ret; | ||
931 | |||
932 | ret = usbhs_pkt_dmadone(pipe); | ||
933 | if (ret < 0) | ||
934 | dev_err(dev, "dma_complete run_error %d : %d\n", | ||
935 | usbhs_pipe_number(pipe), ret); | ||
936 | } | ||
937 | |||
938 | /* | ||
939 | * fifo init | ||
940 | */ | ||
941 | void usbhs_fifo_init(struct usbhs_priv *priv) | ||
942 | { | ||
943 | struct usbhs_mod *mod = usbhs_mod_get_current(priv); | ||
944 | struct usbhs_fifo *cfifo = usbhsf_get_cfifo(priv); | ||
945 | struct usbhs_fifo *d0fifo = usbhsf_get_d0fifo(priv); | ||
946 | struct usbhs_fifo *d1fifo = usbhsf_get_d1fifo(priv); | ||
947 | |||
948 | mod->irq_empty = usbhsf_irq_empty; | ||
949 | mod->irq_ready = usbhsf_irq_ready; | ||
950 | mod->irq_bempsts = 0; | ||
951 | mod->irq_brdysts = 0; | ||
952 | |||
953 | cfifo->pipe = NULL; | ||
954 | cfifo->tx_chan = NULL; | ||
955 | cfifo->rx_chan = NULL; | ||
956 | |||
957 | d0fifo->pipe = NULL; | ||
958 | d0fifo->tx_chan = NULL; | ||
959 | d0fifo->rx_chan = NULL; | ||
960 | |||
961 | d1fifo->pipe = NULL; | ||
962 | d1fifo->tx_chan = NULL; | ||
963 | d1fifo->rx_chan = NULL; | ||
964 | |||
965 | usbhsf_dma_init(priv, usbhsf_get_d0fifo(priv)); | ||
966 | usbhsf_dma_init(priv, usbhsf_get_d1fifo(priv)); | ||
967 | } | ||
968 | |||
969 | void usbhs_fifo_quit(struct usbhs_priv *priv) | ||
970 | { | ||
971 | struct usbhs_mod *mod = usbhs_mod_get_current(priv); | ||
972 | |||
973 | mod->irq_empty = NULL; | ||
974 | mod->irq_ready = NULL; | ||
975 | mod->irq_bempsts = 0; | ||
976 | mod->irq_brdysts = 0; | ||
977 | |||
978 | usbhsf_dma_quit(priv, usbhsf_get_d0fifo(priv)); | ||
979 | usbhsf_dma_quit(priv, usbhsf_get_d1fifo(priv)); | ||
980 | } | ||
981 | |||
982 | int usbhs_fifo_probe(struct usbhs_priv *priv) | ||
983 | { | ||
984 | struct usbhs_fifo *fifo; | ||
985 | |||
986 | /* CFIFO */ | ||
987 | fifo = usbhsf_get_cfifo(priv); | ||
988 | fifo->name = "CFIFO"; | ||
989 | fifo->port = CFIFO; | ||
990 | fifo->sel = CFIFOSEL; | ||
991 | fifo->ctr = CFIFOCTR; | ||
992 | |||
993 | /* D0FIFO */ | ||
994 | fifo = usbhsf_get_d0fifo(priv); | ||
995 | fifo->name = "D0FIFO"; | ||
996 | fifo->port = D0FIFO; | ||
997 | fifo->sel = D0FIFOSEL; | ||
998 | fifo->ctr = D0FIFOCTR; | ||
999 | fifo->tx_slave.slave_id = usbhs_get_dparam(priv, d0_tx_id); | ||
1000 | fifo->rx_slave.slave_id = usbhs_get_dparam(priv, d0_rx_id); | ||
1001 | |||
1002 | /* D1FIFO */ | ||
1003 | fifo = usbhsf_get_d1fifo(priv); | ||
1004 | fifo->name = "D1FIFO"; | ||
1005 | fifo->port = D1FIFO; | ||
1006 | fifo->sel = D1FIFOSEL; | ||
1007 | fifo->ctr = D1FIFOCTR; | ||
1008 | fifo->tx_slave.slave_id = usbhs_get_dparam(priv, d1_tx_id); | ||
1009 | fifo->rx_slave.slave_id = usbhs_get_dparam(priv, d1_rx_id); | ||
1010 | |||
1011 | return 0; | ||
1012 | } | ||
1013 | |||
1014 | void usbhs_fifo_remove(struct usbhs_priv *priv) | ||
1015 | { | ||
1016 | } | ||
diff --git a/drivers/usb/renesas_usbhs/fifo.h b/drivers/usb/renesas_usbhs/fifo.h new file mode 100644 index 00000000000..ed6d8e56c13 --- /dev/null +++ b/drivers/usb/renesas_usbhs/fifo.h | |||
@@ -0,0 +1,104 @@ | |||
1 | /* | ||
2 | * Renesas USB driver | ||
3 | * | ||
4 | * Copyright (C) 2011 Renesas Solutions Corp. | ||
5 | * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
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 | ||
14 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
15 | * | ||
16 | */ | ||
17 | #ifndef RENESAS_USB_FIFO_H | ||
18 | #define RENESAS_USB_FIFO_H | ||
19 | |||
20 | #include <linux/interrupt.h> | ||
21 | #include <linux/sh_dma.h> | ||
22 | #include <asm/dma.h> | ||
23 | #include "pipe.h" | ||
24 | |||
25 | #define DMA_ADDR_INVALID (~(dma_addr_t)0) | ||
26 | |||
27 | struct usbhs_fifo { | ||
28 | char *name; | ||
29 | u32 port; /* xFIFO */ | ||
30 | u32 sel; /* xFIFOSEL */ | ||
31 | u32 ctr; /* xFIFOCTR */ | ||
32 | |||
33 | struct usbhs_pipe *pipe; | ||
34 | struct tasklet_struct tasklet; | ||
35 | |||
36 | struct dma_chan *tx_chan; | ||
37 | struct dma_chan *rx_chan; | ||
38 | |||
39 | struct sh_dmae_slave tx_slave; | ||
40 | struct sh_dmae_slave rx_slave; | ||
41 | }; | ||
42 | |||
43 | struct usbhs_fifo_info { | ||
44 | struct usbhs_fifo cfifo; | ||
45 | struct usbhs_fifo d0fifo; | ||
46 | struct usbhs_fifo d1fifo; | ||
47 | }; | ||
48 | |||
49 | struct usbhs_pkt_handle; | ||
50 | struct usbhs_pkt { | ||
51 | struct list_head node; | ||
52 | struct usbhs_pipe *pipe; | ||
53 | struct usbhs_pkt_handle *handler; | ||
54 | dma_addr_t dma; | ||
55 | void *buf; | ||
56 | int length; | ||
57 | int trans; | ||
58 | int actual; | ||
59 | int zero; | ||
60 | }; | ||
61 | |||
62 | struct usbhs_pkt_handle { | ||
63 | int (*prepare)(struct usbhs_pkt *pkt, int *is_done); | ||
64 | int (*try_run)(struct usbhs_pkt *pkt, int *is_done); | ||
65 | int (*dma_done)(struct usbhs_pkt *pkt, int *is_done); | ||
66 | }; | ||
67 | |||
68 | /* | ||
69 | * fifo | ||
70 | */ | ||
71 | int usbhs_fifo_probe(struct usbhs_priv *priv); | ||
72 | void usbhs_fifo_remove(struct usbhs_priv *priv); | ||
73 | void usbhs_fifo_init(struct usbhs_priv *priv); | ||
74 | void usbhs_fifo_quit(struct usbhs_priv *priv); | ||
75 | |||
76 | /* | ||
77 | * packet info | ||
78 | */ | ||
79 | enum { | ||
80 | USBHSF_PKT_PREPARE, | ||
81 | USBHSF_PKT_TRY_RUN, | ||
82 | USBHSF_PKT_DMA_DONE, | ||
83 | }; | ||
84 | |||
85 | extern struct usbhs_pkt_handle usbhs_fifo_pio_push_handler; | ||
86 | extern struct usbhs_pkt_handle usbhs_fifo_pio_pop_handler; | ||
87 | extern struct usbhs_pkt_handle usbhs_ctrl_stage_end_handler; | ||
88 | |||
89 | extern struct usbhs_pkt_handle usbhs_fifo_dma_push_handler; | ||
90 | extern struct usbhs_pkt_handle usbhs_fifo_dma_pop_handler; | ||
91 | |||
92 | |||
93 | void usbhs_pkt_init(struct usbhs_pkt *pkt); | ||
94 | void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt, | ||
95 | struct usbhs_pkt_handle *handler, | ||
96 | void *buf, int len, int zero); | ||
97 | struct usbhs_pkt *usbhs_pkt_pop(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt); | ||
98 | int __usbhs_pkt_handler(struct usbhs_pipe *pipe, int type); | ||
99 | |||
100 | #define usbhs_pkt_start(p) __usbhs_pkt_handler(p, USBHSF_PKT_PREPARE) | ||
101 | #define usbhs_pkt_run(p) __usbhs_pkt_handler(p, USBHSF_PKT_TRY_RUN) | ||
102 | #define usbhs_pkt_dmadone(p) __usbhs_pkt_handler(p, USBHSF_PKT_DMA_DONE) | ||
103 | |||
104 | #endif /* RENESAS_USB_FIFO_H */ | ||
diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c index 547486ccd05..cb2d451d511 100644 --- a/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/drivers/usb/renesas_usbhs/mod_gadget.c | |||
@@ -14,6 +14,7 @@ | |||
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/dma-mapping.h> | ||
17 | #include <linux/io.h> | 18 | #include <linux/io.h> |
18 | #include <linux/module.h> | 19 | #include <linux/module.h> |
19 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
@@ -26,26 +27,25 @@ | |||
26 | */ | 27 | */ |
27 | struct usbhsg_request { | 28 | struct usbhsg_request { |
28 | struct usb_request req; | 29 | struct usb_request req; |
29 | struct list_head node; | 30 | struct usbhs_pkt pkt; |
30 | }; | 31 | }; |
31 | 32 | ||
32 | #define EP_NAME_SIZE 8 | 33 | #define EP_NAME_SIZE 8 |
33 | struct usbhsg_gpriv; | 34 | struct usbhsg_gpriv; |
34 | struct usbhsg_pipe_handle; | ||
35 | struct usbhsg_uep { | 35 | struct usbhsg_uep { |
36 | struct usb_ep ep; | 36 | struct usb_ep ep; |
37 | struct usbhs_pipe *pipe; | 37 | struct usbhs_pipe *pipe; |
38 | struct list_head list; | ||
39 | 38 | ||
40 | char ep_name[EP_NAME_SIZE]; | 39 | char ep_name[EP_NAME_SIZE]; |
41 | 40 | ||
42 | struct usbhsg_gpriv *gpriv; | 41 | struct usbhsg_gpriv *gpriv; |
43 | struct usbhsg_pipe_handle *handler; | 42 | struct usbhs_pkt_handle *handler; |
44 | }; | 43 | }; |
45 | 44 | ||
46 | struct usbhsg_gpriv { | 45 | struct usbhsg_gpriv { |
47 | struct usb_gadget gadget; | 46 | struct usb_gadget gadget; |
48 | struct usbhs_mod mod; | 47 | struct usbhs_mod mod; |
48 | struct list_head link; | ||
49 | 49 | ||
50 | struct usbhsg_uep *uep; | 50 | struct usbhsg_uep *uep; |
51 | int uep_size; | 51 | int uep_size; |
@@ -58,12 +58,6 @@ struct usbhsg_gpriv { | |||
58 | #define USBHSG_STATUS_WEDGE (1 << 2) | 58 | #define USBHSG_STATUS_WEDGE (1 << 2) |
59 | }; | 59 | }; |
60 | 60 | ||
61 | struct usbhsg_pipe_handle { | ||
62 | int (*prepare)(struct usbhsg_uep *uep, struct usbhsg_request *ureq); | ||
63 | int (*try_run)(struct usbhsg_uep *uep, struct usbhsg_request *ureq); | ||
64 | void (*irq_mask)(struct usbhsg_uep *uep, int enable); | ||
65 | }; | ||
66 | |||
67 | struct usbhsg_recip_handle { | 61 | struct usbhsg_recip_handle { |
68 | char *name; | 62 | char *name; |
69 | int (*device)(struct usbhs_priv *priv, struct usbhsg_uep *uep, | 63 | int (*device)(struct usbhs_priv *priv, struct usbhsg_uep *uep, |
@@ -83,7 +77,7 @@ struct usbhsg_recip_handle { | |||
83 | struct usbhsg_gpriv, mod) | 77 | struct usbhsg_gpriv, mod) |
84 | 78 | ||
85 | #define __usbhsg_for_each_uep(start, pos, g, i) \ | 79 | #define __usbhsg_for_each_uep(start, pos, g, i) \ |
86 | for (i = start, pos = (g)->uep; \ | 80 | for (i = start, pos = (g)->uep + i; \ |
87 | i < (g)->uep_size; \ | 81 | i < (g)->uep_size; \ |
88 | i++, pos = (g)->uep + i) | 82 | i++, pos = (g)->uep + i) |
89 | 83 | ||
@@ -100,7 +94,6 @@ struct usbhsg_recip_handle { | |||
100 | container_of(r, struct usbhsg_request, req) | 94 | container_of(r, struct usbhsg_request, req) |
101 | 95 | ||
102 | #define usbhsg_ep_to_uep(e) container_of(e, struct usbhsg_uep, ep) | 96 | #define usbhsg_ep_to_uep(e) container_of(e, struct usbhsg_uep, ep) |
103 | #define usbhsg_gpriv_to_lock(gp) usbhs_priv_to_lock((gp)->mod.priv) | ||
104 | #define usbhsg_gpriv_to_dev(gp) usbhs_priv_to_dev((gp)->mod.priv) | 97 | #define usbhsg_gpriv_to_dev(gp) usbhs_priv_to_dev((gp)->mod.priv) |
105 | #define usbhsg_gpriv_to_priv(gp) ((gp)->mod.priv) | 98 | #define usbhsg_gpriv_to_priv(gp) ((gp)->mod.priv) |
106 | #define usbhsg_gpriv_to_dcp(gp) ((gp)->uep) | 99 | #define usbhsg_gpriv_to_dcp(gp) ((gp)->uep) |
@@ -110,6 +103,10 @@ struct usbhsg_recip_handle { | |||
110 | #define usbhsg_pipe_to_uep(p) ((p)->mod_private) | 103 | #define usbhsg_pipe_to_uep(p) ((p)->mod_private) |
111 | #define usbhsg_is_dcp(u) ((u) == usbhsg_gpriv_to_dcp((u)->gpriv)) | 104 | #define usbhsg_is_dcp(u) ((u) == usbhsg_gpriv_to_dcp((u)->gpriv)) |
112 | 105 | ||
106 | #define usbhsg_ureq_to_pkt(u) (&(u)->pkt) | ||
107 | #define usbhsg_pkt_to_ureq(i) \ | ||
108 | container_of(i, struct usbhsg_request, pkt) | ||
109 | |||
113 | #define usbhsg_is_not_connected(gp) ((gp)->gadget.speed == USB_SPEED_UNKNOWN) | 110 | #define usbhsg_is_not_connected(gp) ((gp)->gadget.speed == USB_SPEED_UNKNOWN) |
114 | 111 | ||
115 | /* status */ | 112 | /* status */ |
@@ -118,37 +115,18 @@ struct usbhsg_recip_handle { | |||
118 | #define usbhsg_status_clr(gp, b) (gp->status &= ~b) | 115 | #define usbhsg_status_clr(gp, b) (gp->status &= ~b) |
119 | #define usbhsg_status_has(gp, b) (gp->status & b) | 116 | #define usbhsg_status_has(gp, b) (gp->status & b) |
120 | 117 | ||
121 | /* | 118 | /* controller */ |
122 | * usbhsg_trylock | 119 | LIST_HEAD(the_controller_link); |
123 | * | ||
124 | * This driver don't use spin_try_lock | ||
125 | * to avoid warning of CONFIG_DEBUG_SPINLOCK | ||
126 | */ | ||
127 | static spinlock_t *usbhsg_trylock(struct usbhsg_gpriv *gpriv, | ||
128 | unsigned long *flags) | ||
129 | { | ||
130 | spinlock_t *lock = usbhsg_gpriv_to_lock(gpriv); | ||
131 | |||
132 | /* check spin lock status | ||
133 | * to avoid deadlock/nest */ | ||
134 | if (spin_is_locked(lock)) | ||
135 | return NULL; | ||
136 | 120 | ||
137 | spin_lock_irqsave(lock, *flags); | 121 | #define usbhsg_for_each_controller(gpriv)\ |
138 | 122 | list_for_each_entry(gpriv, &the_controller_link, link) | |
139 | return lock; | 123 | #define usbhsg_controller_register(gpriv)\ |
140 | } | 124 | list_add_tail(&(gpriv)->link, &the_controller_link) |
141 | 125 | #define usbhsg_controller_unregister(gpriv)\ | |
142 | static void usbhsg_unlock(spinlock_t *lock, unsigned long *flags) | 126 | list_del_init(&(gpriv)->link) |
143 | { | ||
144 | if (!lock) | ||
145 | return; | ||
146 | |||
147 | spin_unlock_irqrestore(lock, *flags); | ||
148 | } | ||
149 | 127 | ||
150 | /* | 128 | /* |
151 | * list push/pop | 129 | * queue push/pop |
152 | */ | 130 | */ |
153 | static void usbhsg_queue_push(struct usbhsg_uep *uep, | 131 | static void usbhsg_queue_push(struct usbhsg_uep *uep, |
154 | struct usbhsg_request *ureq) | 132 | struct usbhsg_request *ureq) |
@@ -156,79 +134,17 @@ static void usbhsg_queue_push(struct usbhsg_uep *uep, | |||
156 | struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); | 134 | struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); |
157 | struct device *dev = usbhsg_gpriv_to_dev(gpriv); | 135 | struct device *dev = usbhsg_gpriv_to_dev(gpriv); |
158 | struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); | 136 | struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); |
137 | struct usbhs_pkt *pkt = usbhsg_ureq_to_pkt(ureq); | ||
138 | struct usb_request *req = &ureq->req; | ||
159 | 139 | ||
160 | /* | 140 | req->actual = 0; |
161 | ********* assume under spin lock ********* | 141 | req->status = -EINPROGRESS; |
162 | */ | 142 | usbhs_pkt_push(pipe, pkt, uep->handler, |
163 | list_del_init(&ureq->node); | 143 | req->buf, req->length, req->zero); |
164 | list_add_tail(&ureq->node, &uep->list); | ||
165 | ureq->req.actual = 0; | ||
166 | ureq->req.status = -EINPROGRESS; | ||
167 | 144 | ||
168 | dev_dbg(dev, "pipe %d : queue push (%d)\n", | 145 | dev_dbg(dev, "pipe %d : queue push (%d)\n", |
169 | usbhs_pipe_number(pipe), | 146 | usbhs_pipe_number(pipe), |
170 | ureq->req.length); | 147 | req->length); |
171 | } | ||
172 | |||
173 | static struct usbhsg_request *usbhsg_queue_get(struct usbhsg_uep *uep) | ||
174 | { | ||
175 | /* | ||
176 | ********* assume under spin lock ********* | ||
177 | */ | ||
178 | if (list_empty(&uep->list)) | ||
179 | return NULL; | ||
180 | |||
181 | return list_entry(uep->list.next, struct usbhsg_request, node); | ||
182 | } | ||
183 | |||
184 | #define usbhsg_queue_prepare(uep) __usbhsg_queue_handler(uep, 1); | ||
185 | #define usbhsg_queue_handle(uep) __usbhsg_queue_handler(uep, 0); | ||
186 | static int __usbhsg_queue_handler(struct usbhsg_uep *uep, int prepare) | ||
187 | { | ||
188 | struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); | ||
189 | struct device *dev = usbhsg_gpriv_to_dev(gpriv); | ||
190 | struct usbhsg_request *ureq; | ||
191 | spinlock_t *lock; | ||
192 | unsigned long flags; | ||
193 | int ret = 0; | ||
194 | |||
195 | if (!uep->handler) { | ||
196 | dev_err(dev, "no handler function\n"); | ||
197 | return -EIO; | ||
198 | } | ||
199 | |||
200 | /* | ||
201 | * CAUTION [*queue handler*] | ||
202 | * | ||
203 | * This function will be called for start/restart queue operation. | ||
204 | * OTOH the most much worry for USB driver is spinlock nest. | ||
205 | * Specially it are | ||
206 | * - usb_ep_ops :: queue | ||
207 | * - usb_request :: complete | ||
208 | * | ||
209 | * But the caller of this function need not care about spinlock. | ||
210 | * This function is using usbhsg_trylock for it. | ||
211 | * if "is_locked" is 1, this mean this function lock it. | ||
212 | * but if it is 0, this mean it is already under spin lock. | ||
213 | * see also | ||
214 | * CAUTION [*endpoint queue*] | ||
215 | * CAUTION [*request complete*] | ||
216 | */ | ||
217 | |||
218 | /****************** spin try lock *******************/ | ||
219 | lock = usbhsg_trylock(gpriv, &flags); | ||
220 | |||
221 | ureq = usbhsg_queue_get(uep); | ||
222 | if (ureq) { | ||
223 | if (prepare) | ||
224 | ret = uep->handler->prepare(uep, ureq); | ||
225 | else | ||
226 | ret = uep->handler->try_run(uep, ureq); | ||
227 | } | ||
228 | usbhsg_unlock(lock, &flags); | ||
229 | /******************** spin unlock ******************/ | ||
230 | |||
231 | return ret; | ||
232 | } | 148 | } |
233 | 149 | ||
234 | static void usbhsg_queue_pop(struct usbhsg_uep *uep, | 150 | static void usbhsg_queue_pop(struct usbhsg_uep *uep, |
@@ -239,289 +155,91 @@ static void usbhsg_queue_pop(struct usbhsg_uep *uep, | |||
239 | struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); | 155 | struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); |
240 | struct device *dev = usbhsg_gpriv_to_dev(gpriv); | 156 | struct device *dev = usbhsg_gpriv_to_dev(gpriv); |
241 | 157 | ||
242 | /* | ||
243 | ********* assume under spin lock ********* | ||
244 | */ | ||
245 | |||
246 | /* | ||
247 | * CAUTION [*request complete*] | ||
248 | * | ||
249 | * There is a possibility not to be called in correct order | ||
250 | * if "complete" is called without spinlock. | ||
251 | * | ||
252 | * So, this function assume it is under spinlock, | ||
253 | * and call usb_request :: complete. | ||
254 | * | ||
255 | * But this "complete" will push next usb_request. | ||
256 | * It mean "usb_ep_ops :: queue" which is using spinlock is called | ||
257 | * under spinlock. | ||
258 | * | ||
259 | * To avoid dead-lock, this driver is using usbhsg_trylock. | ||
260 | * CAUTION [*endpoint queue*] | ||
261 | * CAUTION [*queue handler*] | ||
262 | */ | ||
263 | |||
264 | dev_dbg(dev, "pipe %d : queue pop\n", usbhs_pipe_number(pipe)); | 158 | dev_dbg(dev, "pipe %d : queue pop\n", usbhs_pipe_number(pipe)); |
265 | 159 | ||
266 | list_del_init(&ureq->node); | ||
267 | |||
268 | ureq->req.status = status; | 160 | ureq->req.status = status; |
269 | ureq->req.complete(&uep->ep, &ureq->req); | 161 | ureq->req.complete(&uep->ep, &ureq->req); |
270 | |||
271 | /* more request ? */ | ||
272 | if (0 == status) | ||
273 | usbhsg_queue_prepare(uep); | ||
274 | } | 162 | } |
275 | 163 | ||
276 | /* | 164 | static void usbhsg_queue_done(struct usbhs_pkt *pkt) |
277 | * irq enable/disable function | ||
278 | */ | ||
279 | #define usbhsg_irq_callback_ctrl(uep, status, enable) \ | ||
280 | ({ \ | ||
281 | struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); \ | ||
282 | struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); \ | ||
283 | struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv); \ | ||
284 | struct usbhs_mod *mod = usbhs_mod_get_current(priv); \ | ||
285 | if (!mod) \ | ||
286 | return; \ | ||
287 | if (enable) \ | ||
288 | mod->irq_##status |= (1 << usbhs_pipe_number(pipe)); \ | ||
289 | else \ | ||
290 | mod->irq_##status &= ~(1 << usbhs_pipe_number(pipe)); \ | ||
291 | usbhs_irq_callback_update(priv, mod); \ | ||
292 | }) | ||
293 | |||
294 | static void usbhsg_irq_empty_ctrl(struct usbhsg_uep *uep, int enable) | ||
295 | { | 165 | { |
296 | usbhsg_irq_callback_ctrl(uep, bempsts, enable); | 166 | struct usbhs_pipe *pipe = pkt->pipe; |
297 | } | 167 | struct usbhsg_uep *uep = usbhsg_pipe_to_uep(pipe); |
168 | struct usbhsg_request *ureq = usbhsg_pkt_to_ureq(pkt); | ||
298 | 169 | ||
299 | static void usbhsg_irq_ready_ctrl(struct usbhsg_uep *uep, int enable) | 170 | ureq->req.actual = pkt->actual; |
300 | { | ||
301 | usbhsg_irq_callback_ctrl(uep, brdysts, enable); | ||
302 | } | ||
303 | |||
304 | /* | ||
305 | * handler function | ||
306 | */ | ||
307 | static int usbhsg_try_run_ctrl_stage_end(struct usbhsg_uep *uep, | ||
308 | struct usbhsg_request *ureq) | ||
309 | { | ||
310 | struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); | ||
311 | |||
312 | /* | ||
313 | ********* assume under spin lock ********* | ||
314 | */ | ||
315 | 171 | ||
316 | usbhs_dcp_control_transfer_done(pipe); | ||
317 | usbhsg_queue_pop(uep, ureq, 0); | 172 | usbhsg_queue_pop(uep, ureq, 0); |
318 | |||
319 | return 0; | ||
320 | } | 173 | } |
321 | 174 | ||
322 | static int usbhsg_try_run_send_packet(struct usbhsg_uep *uep, | 175 | /* |
323 | struct usbhsg_request *ureq) | 176 | * dma map/unmap |
177 | */ | ||
178 | static int usbhsg_dma_map(struct device *dev, | ||
179 | struct usbhs_pkt *pkt, | ||
180 | enum dma_data_direction dir) | ||
324 | { | 181 | { |
325 | struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); | 182 | struct usbhsg_request *ureq = usbhsg_pkt_to_ureq(pkt); |
326 | struct usb_request *req = &ureq->req; | 183 | struct usb_request *req = &ureq->req; |
327 | struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); | ||
328 | struct device *dev = usbhsg_gpriv_to_dev(gpriv); | ||
329 | void *buf; | ||
330 | int remainder, send; | ||
331 | int is_done = 0; | ||
332 | int enable; | ||
333 | int maxp; | ||
334 | 184 | ||
335 | /* | 185 | if (pkt->dma != DMA_ADDR_INVALID) { |
336 | ********* assume under spin lock ********* | 186 | dev_err(dev, "dma is already mapped\n"); |
337 | */ | 187 | return -EIO; |
338 | |||
339 | maxp = usbhs_pipe_get_maxpacket(pipe); | ||
340 | buf = req->buf + req->actual; | ||
341 | remainder = req->length - req->actual; | ||
342 | |||
343 | send = usbhs_fifo_write(pipe, buf, remainder); | ||
344 | |||
345 | /* | ||
346 | * send < 0 : pipe busy | ||
347 | * send = 0 : send zero packet | ||
348 | * send > 0 : send data | ||
349 | * | ||
350 | * send <= max_packet | ||
351 | */ | ||
352 | if (send > 0) | ||
353 | req->actual += send; | ||
354 | |||
355 | /* send all packet ? */ | ||
356 | if (send < remainder) | ||
357 | is_done = 0; /* there are remainder data */ | ||
358 | else if (send < maxp) | ||
359 | is_done = 1; /* short packet */ | ||
360 | else | ||
361 | is_done = !req->zero; /* send zero packet ? */ | ||
362 | |||
363 | dev_dbg(dev, " send %d (%d/ %d/ %d/ %d)\n", | ||
364 | usbhs_pipe_number(pipe), | ||
365 | remainder, send, is_done, req->zero); | ||
366 | |||
367 | /* | ||
368 | * enable interrupt and send again in irq handler | ||
369 | * if it still have remainder data which should be sent. | ||
370 | */ | ||
371 | enable = !is_done; | ||
372 | uep->handler->irq_mask(uep, enable); | ||
373 | |||
374 | /* | ||
375 | * usbhs_fifo_enable execute | ||
376 | * - after callback_update, | ||
377 | * - before queue_pop / stage_end | ||
378 | */ | ||
379 | usbhs_fifo_enable(pipe); | ||
380 | |||
381 | /* | ||
382 | * all data were sent ? | ||
383 | */ | ||
384 | if (is_done) { | ||
385 | /* it care below call in | ||
386 | "function mode" */ | ||
387 | if (usbhsg_is_dcp(uep)) | ||
388 | usbhs_dcp_control_transfer_done(pipe); | ||
389 | |||
390 | usbhsg_queue_pop(uep, ureq, 0); | ||
391 | } | 188 | } |
392 | 189 | ||
393 | return 0; | 190 | if (req->dma == DMA_ADDR_INVALID) { |
394 | } | 191 | pkt->dma = dma_map_single(dev, pkt->buf, pkt->length, dir); |
395 | 192 | } else { | |
396 | static int usbhsg_prepare_send_packet(struct usbhsg_uep *uep, | 193 | dma_sync_single_for_device(dev, req->dma, req->length, dir); |
397 | struct usbhsg_request *ureq) | 194 | pkt->dma = req->dma; |
398 | { | 195 | } |
399 | struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); | ||
400 | |||
401 | /* | ||
402 | ********* assume under spin lock ********* | ||
403 | */ | ||
404 | 196 | ||
405 | usbhs_fifo_prepare_write(pipe); | 197 | if (dma_mapping_error(dev, pkt->dma)) { |
406 | usbhsg_try_run_send_packet(uep, ureq); | 198 | dev_err(dev, "dma mapping error %x\n", pkt->dma); |
199 | return -EIO; | ||
200 | } | ||
407 | 201 | ||
408 | return 0; | 202 | return 0; |
409 | } | 203 | } |
410 | 204 | ||
411 | static int usbhsg_try_run_receive_packet(struct usbhsg_uep *uep, | 205 | static int usbhsg_dma_unmap(struct device *dev, |
412 | struct usbhsg_request *ureq) | 206 | struct usbhs_pkt *pkt, |
207 | enum dma_data_direction dir) | ||
413 | { | 208 | { |
414 | struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); | 209 | struct usbhsg_request *ureq = usbhsg_pkt_to_ureq(pkt); |
415 | struct usb_request *req = &ureq->req; | 210 | struct usb_request *req = &ureq->req; |
416 | struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); | ||
417 | struct device *dev = usbhsg_gpriv_to_dev(gpriv); | ||
418 | void *buf; | ||
419 | int maxp; | ||
420 | int remainder, recv; | ||
421 | int is_done = 0; | ||
422 | |||
423 | /* | ||
424 | ********* assume under spin lock ********* | ||
425 | */ | ||
426 | |||
427 | maxp = usbhs_pipe_get_maxpacket(pipe); | ||
428 | buf = req->buf + req->actual; | ||
429 | remainder = req->length - req->actual; | ||
430 | |||
431 | recv = usbhs_fifo_read(pipe, buf, remainder); | ||
432 | /* | ||
433 | * recv < 0 : pipe busy | ||
434 | * recv >= 0 : receive data | ||
435 | * | ||
436 | * recv <= max_packet | ||
437 | */ | ||
438 | if (recv < 0) | ||
439 | return -EBUSY; | ||
440 | |||
441 | /* update parameters */ | ||
442 | req->actual += recv; | ||
443 | |||
444 | if ((recv == remainder) || /* receive all data */ | ||
445 | (recv < maxp)) /* short packet */ | ||
446 | is_done = 1; | ||
447 | 211 | ||
448 | dev_dbg(dev, " recv %d (%d/ %d/ %d/ %d)\n", | 212 | if (pkt->dma == DMA_ADDR_INVALID) { |
449 | usbhs_pipe_number(pipe), | 213 | dev_err(dev, "dma is not mapped\n"); |
450 | remainder, recv, is_done, req->zero); | 214 | return -EIO; |
215 | } | ||
451 | 216 | ||
452 | /* read all data ? */ | 217 | if (req->dma == DMA_ADDR_INVALID) |
453 | if (is_done) { | 218 | dma_unmap_single(dev, pkt->dma, pkt->length, dir); |
454 | int disable = 0; | 219 | else |
220 | dma_sync_single_for_cpu(dev, req->dma, req->length, dir); | ||
455 | 221 | ||
456 | uep->handler->irq_mask(uep, disable); | 222 | pkt->dma = DMA_ADDR_INVALID; |
457 | usbhs_fifo_disable(pipe); | ||
458 | usbhsg_queue_pop(uep, ureq, 0); | ||
459 | } | ||
460 | 223 | ||
461 | return 0; | 224 | return 0; |
462 | } | 225 | } |
463 | 226 | ||
464 | static int usbhsg_prepare_receive_packet(struct usbhsg_uep *uep, | 227 | static int usbhsg_dma_map_ctrl(struct usbhs_pkt *pkt, int map) |
465 | struct usbhsg_request *ureq) | ||
466 | { | 228 | { |
467 | struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); | 229 | struct usbhs_pipe *pipe = pkt->pipe; |
468 | int enable = 1; | 230 | struct usbhsg_uep *uep = usbhsg_pipe_to_uep(pipe); |
469 | int ret; | 231 | struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); |
470 | 232 | struct device *dev = usbhsg_gpriv_to_dev(gpriv); | |
471 | /* | 233 | enum dma_data_direction dir; |
472 | ********* assume under spin lock ********* | ||
473 | */ | ||
474 | |||
475 | ret = usbhs_fifo_prepare_read(pipe); | ||
476 | if (ret < 0) | ||
477 | return ret; | ||
478 | 234 | ||
479 | /* | 235 | dir = usbhs_pipe_is_dir_in(pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE; |
480 | * data will be read in interrupt handler | ||
481 | */ | ||
482 | uep->handler->irq_mask(uep, enable); | ||
483 | 236 | ||
484 | return ret; | 237 | if (map) |
238 | return usbhsg_dma_map(dev, pkt, dir); | ||
239 | else | ||
240 | return usbhsg_dma_unmap(dev, pkt, dir); | ||
485 | } | 241 | } |
486 | 242 | ||
487 | static struct usbhsg_pipe_handle usbhsg_handler_send_by_empty = { | ||
488 | .prepare = usbhsg_prepare_send_packet, | ||
489 | .try_run = usbhsg_try_run_send_packet, | ||
490 | .irq_mask = usbhsg_irq_empty_ctrl, | ||
491 | }; | ||
492 | |||
493 | static struct usbhsg_pipe_handle usbhsg_handler_send_by_ready = { | ||
494 | .prepare = usbhsg_prepare_send_packet, | ||
495 | .try_run = usbhsg_try_run_send_packet, | ||
496 | .irq_mask = usbhsg_irq_ready_ctrl, | ||
497 | }; | ||
498 | |||
499 | static struct usbhsg_pipe_handle usbhsg_handler_recv_by_ready = { | ||
500 | .prepare = usbhsg_prepare_receive_packet, | ||
501 | .try_run = usbhsg_try_run_receive_packet, | ||
502 | .irq_mask = usbhsg_irq_ready_ctrl, | ||
503 | }; | ||
504 | |||
505 | static struct usbhsg_pipe_handle usbhsg_handler_ctrl_stage_end = { | ||
506 | .prepare = usbhsg_try_run_ctrl_stage_end, | ||
507 | .try_run = usbhsg_try_run_ctrl_stage_end, | ||
508 | }; | ||
509 | |||
510 | /* | ||
511 | * DCP pipe can NOT use "ready interrupt" for "send" | ||
512 | * it should use "empty" interrupt. | ||
513 | * see | ||
514 | * "Operation" - "Interrupt Function" - "BRDY Interrupt" | ||
515 | * | ||
516 | * on the other hand, normal pipe can use "ready interrupt" for "send" | ||
517 | * even though it is single/double buffer | ||
518 | */ | ||
519 | #define usbhsg_handler_send_ctrl usbhsg_handler_send_by_empty | ||
520 | #define usbhsg_handler_recv_ctrl usbhsg_handler_recv_by_ready | ||
521 | |||
522 | #define usbhsg_handler_send_packet usbhsg_handler_send_by_ready | ||
523 | #define usbhsg_handler_recv_packet usbhsg_handler_recv_by_ready | ||
524 | |||
525 | /* | 243 | /* |
526 | * USB_TYPE_STANDARD / clear feature functions | 244 | * USB_TYPE_STANDARD / clear feature functions |
527 | */ | 245 | */ |
@@ -546,15 +264,13 @@ static int usbhsg_recip_handler_std_clear_endpoint(struct usbhs_priv *priv, | |||
546 | struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); | 264 | struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); |
547 | 265 | ||
548 | if (!usbhsg_status_has(gpriv, USBHSG_STATUS_WEDGE)) { | 266 | if (!usbhsg_status_has(gpriv, USBHSG_STATUS_WEDGE)) { |
549 | usbhs_fifo_disable(pipe); | 267 | usbhs_pipe_disable(pipe); |
550 | usbhs_pipe_clear_sequence(pipe); | 268 | usbhs_pipe_clear_sequence(pipe); |
551 | usbhs_fifo_enable(pipe); | 269 | usbhs_pipe_enable(pipe); |
552 | } | 270 | } |
553 | 271 | ||
554 | usbhsg_recip_handler_std_control_done(priv, uep, ctrl); | 272 | usbhsg_recip_handler_std_control_done(priv, uep, ctrl); |
555 | 273 | ||
556 | usbhsg_queue_prepare(uep); | ||
557 | |||
558 | return 0; | 274 | return 0; |
559 | } | 275 | } |
560 | 276 | ||
@@ -575,6 +291,7 @@ static int usbhsg_recip_run_handle(struct usbhs_priv *priv, | |||
575 | struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); | 291 | struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); |
576 | struct device *dev = usbhsg_gpriv_to_dev(gpriv); | 292 | struct device *dev = usbhsg_gpriv_to_dev(gpriv); |
577 | struct usbhsg_uep *uep; | 293 | struct usbhsg_uep *uep; |
294 | struct usbhs_pipe *pipe; | ||
578 | int recip = ctrl->bRequestType & USB_RECIP_MASK; | 295 | int recip = ctrl->bRequestType & USB_RECIP_MASK; |
579 | int nth = le16_to_cpu(ctrl->wIndex) & USB_ENDPOINT_NUMBER_MASK; | 296 | int nth = le16_to_cpu(ctrl->wIndex) & USB_ENDPOINT_NUMBER_MASK; |
580 | int ret; | 297 | int ret; |
@@ -583,9 +300,11 @@ static int usbhsg_recip_run_handle(struct usbhs_priv *priv, | |||
583 | char *msg; | 300 | char *msg; |
584 | 301 | ||
585 | uep = usbhsg_gpriv_to_nth_uep(gpriv, nth); | 302 | uep = usbhsg_gpriv_to_nth_uep(gpriv, nth); |
586 | if (!usbhsg_uep_to_pipe(uep)) { | 303 | pipe = usbhsg_uep_to_pipe(uep); |
304 | if (!pipe) { | ||
587 | dev_err(dev, "wrong recip request\n"); | 305 | dev_err(dev, "wrong recip request\n"); |
588 | return -EINVAL; | 306 | ret = -EINVAL; |
307 | goto usbhsg_recip_run_handle_end; | ||
589 | } | 308 | } |
590 | 309 | ||
591 | switch (recip) { | 310 | switch (recip) { |
@@ -608,10 +327,20 @@ static int usbhsg_recip_run_handle(struct usbhs_priv *priv, | |||
608 | } | 327 | } |
609 | 328 | ||
610 | if (func) { | 329 | if (func) { |
330 | unsigned long flags; | ||
331 | |||
611 | dev_dbg(dev, "%s (pipe %d :%s)\n", handler->name, nth, msg); | 332 | dev_dbg(dev, "%s (pipe %d :%s)\n", handler->name, nth, msg); |
333 | |||
334 | /******************** spin lock ********************/ | ||
335 | usbhs_lock(priv, flags); | ||
612 | ret = func(priv, uep, ctrl); | 336 | ret = func(priv, uep, ctrl); |
337 | usbhs_unlock(priv, flags); | ||
338 | /******************** spin unlock ******************/ | ||
613 | } | 339 | } |
614 | 340 | ||
341 | usbhsg_recip_run_handle_end: | ||
342 | usbhs_pkt_start(pipe); | ||
343 | |||
615 | return ret; | 344 | return ret; |
616 | } | 345 | } |
617 | 346 | ||
@@ -660,13 +389,13 @@ static int usbhsg_irq_ctrl_stage(struct usbhs_priv *priv, | |||
660 | 389 | ||
661 | switch (stage) { | 390 | switch (stage) { |
662 | case READ_DATA_STAGE: | 391 | case READ_DATA_STAGE: |
663 | dcp->handler = &usbhsg_handler_send_ctrl; | 392 | dcp->handler = &usbhs_fifo_pio_push_handler; |
664 | break; | 393 | break; |
665 | case WRITE_DATA_STAGE: | 394 | case WRITE_DATA_STAGE: |
666 | dcp->handler = &usbhsg_handler_recv_ctrl; | 395 | dcp->handler = &usbhs_fifo_pio_pop_handler; |
667 | break; | 396 | break; |
668 | case NODATA_STATUS_STAGE: | 397 | case NODATA_STATUS_STAGE: |
669 | dcp->handler = &usbhsg_handler_ctrl_stage_end; | 398 | dcp->handler = &usbhs_ctrl_stage_end_handler; |
670 | break; | 399 | break; |
671 | default: | 400 | default: |
672 | return ret; | 401 | return ret; |
@@ -695,128 +424,27 @@ static int usbhsg_irq_ctrl_stage(struct usbhs_priv *priv, | |||
695 | ret = gpriv->driver->setup(&gpriv->gadget, &ctrl); | 424 | ret = gpriv->driver->setup(&gpriv->gadget, &ctrl); |
696 | 425 | ||
697 | if (ret < 0) | 426 | if (ret < 0) |
698 | usbhs_fifo_stall(pipe); | 427 | usbhs_pipe_stall(pipe); |
699 | 428 | ||
700 | return ret; | 429 | return ret; |
701 | } | 430 | } |
702 | 431 | ||
703 | static int usbhsg_irq_empty(struct usbhs_priv *priv, | ||
704 | struct usbhs_irq_state *irq_state) | ||
705 | { | ||
706 | struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); | ||
707 | struct usbhsg_uep *uep; | ||
708 | struct usbhs_pipe *pipe; | ||
709 | struct device *dev = usbhsg_gpriv_to_dev(gpriv); | ||
710 | int i, ret; | ||
711 | |||
712 | if (!irq_state->bempsts) { | ||
713 | dev_err(dev, "debug %s !!\n", __func__); | ||
714 | return -EIO; | ||
715 | } | ||
716 | |||
717 | dev_dbg(dev, "irq empty [0x%04x]\n", irq_state->bempsts); | ||
718 | |||
719 | /* | ||
720 | * search interrupted "pipe" | ||
721 | * not "uep". | ||
722 | */ | ||
723 | usbhs_for_each_pipe_with_dcp(pipe, priv, i) { | ||
724 | if (!(irq_state->bempsts & (1 << i))) | ||
725 | continue; | ||
726 | |||
727 | uep = usbhsg_pipe_to_uep(pipe); | ||
728 | ret = usbhsg_queue_handle(uep); | ||
729 | if (ret < 0) | ||
730 | dev_err(dev, "send error %d : %d\n", i, ret); | ||
731 | } | ||
732 | |||
733 | return 0; | ||
734 | } | ||
735 | |||
736 | static int usbhsg_irq_ready(struct usbhs_priv *priv, | ||
737 | struct usbhs_irq_state *irq_state) | ||
738 | { | ||
739 | struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); | ||
740 | struct usbhsg_uep *uep; | ||
741 | struct usbhs_pipe *pipe; | ||
742 | struct device *dev = usbhsg_gpriv_to_dev(gpriv); | ||
743 | int i, ret; | ||
744 | |||
745 | if (!irq_state->brdysts) { | ||
746 | dev_err(dev, "debug %s !!\n", __func__); | ||
747 | return -EIO; | ||
748 | } | ||
749 | |||
750 | dev_dbg(dev, "irq ready [0x%04x]\n", irq_state->brdysts); | ||
751 | |||
752 | /* | ||
753 | * search interrupted "pipe" | ||
754 | * not "uep". | ||
755 | */ | ||
756 | usbhs_for_each_pipe_with_dcp(pipe, priv, i) { | ||
757 | if (!(irq_state->brdysts & (1 << i))) | ||
758 | continue; | ||
759 | |||
760 | uep = usbhsg_pipe_to_uep(pipe); | ||
761 | ret = usbhsg_queue_handle(uep); | ||
762 | if (ret < 0) | ||
763 | dev_err(dev, "receive error %d : %d\n", i, ret); | ||
764 | } | ||
765 | |||
766 | return 0; | ||
767 | } | ||
768 | |||
769 | /* | 432 | /* |
770 | * | 433 | * |
771 | * usb_dcp_ops | 434 | * usb_dcp_ops |
772 | * | 435 | * |
773 | */ | 436 | */ |
774 | static int usbhsg_dcp_enable(struct usbhsg_uep *uep) | ||
775 | { | ||
776 | struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); | ||
777 | struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv); | ||
778 | struct usbhs_pipe *pipe; | ||
779 | |||
780 | /* | ||
781 | ********* assume under spin lock ********* | ||
782 | */ | ||
783 | |||
784 | pipe = usbhs_dcp_malloc(priv); | ||
785 | if (!pipe) | ||
786 | return -EIO; | ||
787 | |||
788 | uep->pipe = pipe; | ||
789 | uep->pipe->mod_private = uep; | ||
790 | INIT_LIST_HEAD(&uep->list); | ||
791 | |||
792 | return 0; | ||
793 | } | ||
794 | |||
795 | #define usbhsg_dcp_disable usbhsg_pipe_disable | ||
796 | static int usbhsg_pipe_disable(struct usbhsg_uep *uep) | 437 | static int usbhsg_pipe_disable(struct usbhsg_uep *uep) |
797 | { | 438 | { |
798 | struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); | 439 | struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); |
799 | struct usbhsg_request *ureq; | 440 | struct usbhs_pkt *pkt; |
800 | int disable = 0; | ||
801 | |||
802 | /* | ||
803 | ********* assume under spin lock ********* | ||
804 | */ | ||
805 | 441 | ||
806 | usbhs_fifo_disable(pipe); | 442 | usbhs_pipe_disable(pipe); |
807 | |||
808 | /* | ||
809 | * disable pipe irq | ||
810 | */ | ||
811 | usbhsg_irq_empty_ctrl(uep, disable); | ||
812 | usbhsg_irq_ready_ctrl(uep, disable); | ||
813 | 443 | ||
814 | while (1) { | 444 | while (1) { |
815 | ureq = usbhsg_queue_get(uep); | 445 | pkt = usbhs_pkt_pop(pipe, NULL); |
816 | if (!ureq) | 446 | if (!pkt) |
817 | break; | 447 | break; |
818 | |||
819 | usbhsg_queue_pop(uep, ureq, -ECONNRESET); | ||
820 | } | 448 | } |
821 | 449 | ||
822 | return 0; | 450 | return 0; |
@@ -843,57 +471,44 @@ static int usbhsg_ep_enable(struct usb_ep *ep, | |||
843 | struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); | 471 | struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); |
844 | struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv); | 472 | struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv); |
845 | struct usbhs_pipe *pipe; | 473 | struct usbhs_pipe *pipe; |
846 | spinlock_t *lock; | ||
847 | unsigned long flags; | ||
848 | int ret = -EIO; | 474 | int ret = -EIO; |
849 | 475 | ||
850 | /* | 476 | /* |
851 | * if it already have pipe, | 477 | * if it already have pipe, |
852 | * nothing to do | 478 | * nothing to do |
853 | */ | 479 | */ |
854 | if (uep->pipe) | 480 | if (uep->pipe) { |
481 | usbhs_pipe_clear(uep->pipe); | ||
482 | usbhs_pipe_clear_sequence(uep->pipe); | ||
855 | return 0; | 483 | return 0; |
856 | 484 | } | |
857 | /******************** spin lock ********************/ | ||
858 | lock = usbhsg_trylock(gpriv, &flags); | ||
859 | 485 | ||
860 | pipe = usbhs_pipe_malloc(priv, desc); | 486 | pipe = usbhs_pipe_malloc(priv, desc); |
861 | if (pipe) { | 487 | if (pipe) { |
862 | uep->pipe = pipe; | 488 | uep->pipe = pipe; |
863 | pipe->mod_private = uep; | 489 | pipe->mod_private = uep; |
864 | INIT_LIST_HEAD(&uep->list); | ||
865 | 490 | ||
491 | /* | ||
492 | * usbhs_fifo_dma_push/pop_handler try to | ||
493 | * use dmaengine if possible. | ||
494 | * It will use pio handler if impossible. | ||
495 | */ | ||
866 | if (usb_endpoint_dir_in(desc)) | 496 | if (usb_endpoint_dir_in(desc)) |
867 | uep->handler = &usbhsg_handler_send_packet; | 497 | uep->handler = &usbhs_fifo_dma_push_handler; |
868 | else | 498 | else |
869 | uep->handler = &usbhsg_handler_recv_packet; | 499 | uep->handler = &usbhs_fifo_dma_pop_handler; |
870 | 500 | ||
871 | ret = 0; | 501 | ret = 0; |
872 | } | 502 | } |
873 | 503 | ||
874 | usbhsg_unlock(lock, &flags); | ||
875 | /******************** spin unlock ******************/ | ||
876 | |||
877 | return ret; | 504 | return ret; |
878 | } | 505 | } |
879 | 506 | ||
880 | static int usbhsg_ep_disable(struct usb_ep *ep) | 507 | static int usbhsg_ep_disable(struct usb_ep *ep) |
881 | { | 508 | { |
882 | struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep); | 509 | struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep); |
883 | struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); | ||
884 | spinlock_t *lock; | ||
885 | unsigned long flags; | ||
886 | int ret; | ||
887 | |||
888 | /******************** spin lock ********************/ | ||
889 | lock = usbhsg_trylock(gpriv, &flags); | ||
890 | 510 | ||
891 | ret = usbhsg_pipe_disable(uep); | 511 | return usbhsg_pipe_disable(uep); |
892 | |||
893 | usbhsg_unlock(lock, &flags); | ||
894 | /******************** spin unlock ******************/ | ||
895 | |||
896 | return ret; | ||
897 | } | 512 | } |
898 | 513 | ||
899 | static struct usb_request *usbhsg_ep_alloc_request(struct usb_ep *ep, | 514 | static struct usb_request *usbhsg_ep_alloc_request(struct usb_ep *ep, |
@@ -905,7 +520,10 @@ static struct usb_request *usbhsg_ep_alloc_request(struct usb_ep *ep, | |||
905 | if (!ureq) | 520 | if (!ureq) |
906 | return NULL; | 521 | return NULL; |
907 | 522 | ||
908 | INIT_LIST_HEAD(&ureq->node); | 523 | usbhs_pkt_init(usbhsg_ureq_to_pkt(ureq)); |
524 | |||
525 | ureq->req.dma = DMA_ADDR_INVALID; | ||
526 | |||
909 | return &ureq->req; | 527 | return &ureq->req; |
910 | } | 528 | } |
911 | 529 | ||
@@ -914,7 +532,7 @@ static void usbhsg_ep_free_request(struct usb_ep *ep, | |||
914 | { | 532 | { |
915 | struct usbhsg_request *ureq = usbhsg_req_to_ureq(req); | 533 | struct usbhsg_request *ureq = usbhsg_req_to_ureq(req); |
916 | 534 | ||
917 | WARN_ON(!list_empty(&ureq->node)); | 535 | WARN_ON(!list_empty(&ureq->pkt.node)); |
918 | kfree(ureq); | 536 | kfree(ureq); |
919 | } | 537 | } |
920 | 538 | ||
@@ -925,69 +543,27 @@ static int usbhsg_ep_queue(struct usb_ep *ep, struct usb_request *req, | |||
925 | struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); | 543 | struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); |
926 | struct usbhsg_request *ureq = usbhsg_req_to_ureq(req); | 544 | struct usbhsg_request *ureq = usbhsg_req_to_ureq(req); |
927 | struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); | 545 | struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); |
928 | spinlock_t *lock; | ||
929 | unsigned long flags; | ||
930 | int ret = 0; | ||
931 | |||
932 | /* | ||
933 | * CAUTION [*endpoint queue*] | ||
934 | * | ||
935 | * This function will be called from usb_request :: complete | ||
936 | * or usb driver timing. | ||
937 | * If this function is called from usb_request :: complete, | ||
938 | * it is already under spinlock on this driver. | ||
939 | * but it is called frm usb driver, this function should call spinlock. | ||
940 | * | ||
941 | * This function is using usbshg_trylock to solve this issue. | ||
942 | * if "is_locked" is 1, this mean this function lock it. | ||
943 | * but if it is 0, this mean it is already under spin lock. | ||
944 | * see also | ||
945 | * CAUTION [*queue handler*] | ||
946 | * CAUTION [*request complete*] | ||
947 | */ | ||
948 | |||
949 | /******************** spin lock ********************/ | ||
950 | lock = usbhsg_trylock(gpriv, &flags); | ||
951 | 546 | ||
952 | /* param check */ | 547 | /* param check */ |
953 | if (usbhsg_is_not_connected(gpriv) || | 548 | if (usbhsg_is_not_connected(gpriv) || |
954 | unlikely(!gpriv->driver) || | 549 | unlikely(!gpriv->driver) || |
955 | unlikely(!pipe)) | 550 | unlikely(!pipe)) |
956 | ret = -ESHUTDOWN; | 551 | return -ESHUTDOWN; |
957 | else | ||
958 | usbhsg_queue_push(uep, ureq); | ||
959 | |||
960 | usbhsg_unlock(lock, &flags); | ||
961 | /******************** spin unlock ******************/ | ||
962 | 552 | ||
963 | usbhsg_queue_prepare(uep); | 553 | usbhsg_queue_push(uep, ureq); |
964 | 554 | ||
965 | return ret; | 555 | return 0; |
966 | } | 556 | } |
967 | 557 | ||
968 | static int usbhsg_ep_dequeue(struct usb_ep *ep, struct usb_request *req) | 558 | static int usbhsg_ep_dequeue(struct usb_ep *ep, struct usb_request *req) |
969 | { | 559 | { |
970 | struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep); | 560 | struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep); |
971 | struct usbhsg_request *ureq = usbhsg_req_to_ureq(req); | 561 | struct usbhsg_request *ureq = usbhsg_req_to_ureq(req); |
972 | struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); | 562 | struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); |
973 | spinlock_t *lock; | ||
974 | unsigned long flags; | ||
975 | |||
976 | /* | ||
977 | * see | ||
978 | * CAUTION [*queue handler*] | ||
979 | * CAUTION [*endpoint queue*] | ||
980 | * CAUTION [*request complete*] | ||
981 | */ | ||
982 | |||
983 | /******************** spin lock ********************/ | ||
984 | lock = usbhsg_trylock(gpriv, &flags); | ||
985 | 563 | ||
564 | usbhs_pkt_pop(pipe, usbhsg_ureq_to_pkt(ureq)); | ||
986 | usbhsg_queue_pop(uep, ureq, -ECONNRESET); | 565 | usbhsg_queue_pop(uep, ureq, -ECONNRESET); |
987 | 566 | ||
988 | usbhsg_unlock(lock, &flags); | ||
989 | /******************** spin unlock ******************/ | ||
990 | |||
991 | return 0; | 567 | return 0; |
992 | } | 568 | } |
993 | 569 | ||
@@ -996,42 +572,32 @@ static int __usbhsg_ep_set_halt_wedge(struct usb_ep *ep, int halt, int wedge) | |||
996 | struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep); | 572 | struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep); |
997 | struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); | 573 | struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); |
998 | struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); | 574 | struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); |
575 | struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv); | ||
999 | struct device *dev = usbhsg_gpriv_to_dev(gpriv); | 576 | struct device *dev = usbhsg_gpriv_to_dev(gpriv); |
1000 | spinlock_t *lock; | ||
1001 | unsigned long flags; | 577 | unsigned long flags; |
1002 | int ret = -EAGAIN; | ||
1003 | 578 | ||
1004 | /* | 579 | usbhsg_pipe_disable(uep); |
1005 | * see | ||
1006 | * CAUTION [*queue handler*] | ||
1007 | * CAUTION [*endpoint queue*] | ||
1008 | * CAUTION [*request complete*] | ||
1009 | */ | ||
1010 | 580 | ||
1011 | /******************** spin lock ********************/ | 581 | dev_dbg(dev, "set halt %d (pipe %d)\n", |
1012 | lock = usbhsg_trylock(gpriv, &flags); | 582 | halt, usbhs_pipe_number(pipe)); |
1013 | if (!usbhsg_queue_get(uep)) { | ||
1014 | 583 | ||
1015 | dev_dbg(dev, "set halt %d (pipe %d)\n", | 584 | /******************** spin lock ********************/ |
1016 | halt, usbhs_pipe_number(pipe)); | 585 | usbhs_lock(priv, flags); |
1017 | |||
1018 | if (halt) | ||
1019 | usbhs_fifo_stall(pipe); | ||
1020 | else | ||
1021 | usbhs_fifo_disable(pipe); | ||
1022 | 586 | ||
1023 | if (halt && wedge) | 587 | if (halt) |
1024 | usbhsg_status_set(gpriv, USBHSG_STATUS_WEDGE); | 588 | usbhs_pipe_stall(pipe); |
1025 | else | 589 | else |
1026 | usbhsg_status_clr(gpriv, USBHSG_STATUS_WEDGE); | 590 | usbhs_pipe_disable(pipe); |
1027 | 591 | ||
1028 | ret = 0; | 592 | if (halt && wedge) |
1029 | } | 593 | usbhsg_status_set(gpriv, USBHSG_STATUS_WEDGE); |
594 | else | ||
595 | usbhsg_status_clr(gpriv, USBHSG_STATUS_WEDGE); | ||
1030 | 596 | ||
1031 | usbhsg_unlock(lock, &flags); | 597 | usbhs_unlock(priv, flags); |
1032 | /******************** spin unlock ******************/ | 598 | /******************** spin unlock ******************/ |
1033 | 599 | ||
1034 | return ret; | 600 | return 0; |
1035 | } | 601 | } |
1036 | 602 | ||
1037 | static int usbhsg_ep_set_halt(struct usb_ep *ep, int value) | 603 | static int usbhsg_ep_set_halt(struct usb_ep *ep, int value) |
@@ -1067,28 +633,40 @@ static int usbhsg_try_start(struct usbhs_priv *priv, u32 status) | |||
1067 | struct usbhsg_uep *dcp = usbhsg_gpriv_to_dcp(gpriv); | 633 | struct usbhsg_uep *dcp = usbhsg_gpriv_to_dcp(gpriv); |
1068 | struct usbhs_mod *mod = usbhs_mod_get_current(priv); | 634 | struct usbhs_mod *mod = usbhs_mod_get_current(priv); |
1069 | struct device *dev = usbhs_priv_to_dev(priv); | 635 | struct device *dev = usbhs_priv_to_dev(priv); |
1070 | spinlock_t *lock; | ||
1071 | unsigned long flags; | 636 | unsigned long flags; |
637 | int ret = 0; | ||
1072 | 638 | ||
1073 | /******************** spin lock ********************/ | 639 | /******************** spin lock ********************/ |
1074 | lock = usbhsg_trylock(gpriv, &flags); | 640 | usbhs_lock(priv, flags); |
1075 | 641 | ||
1076 | /* | ||
1077 | * enable interrupt and systems if ready | ||
1078 | */ | ||
1079 | usbhsg_status_set(gpriv, status); | 642 | usbhsg_status_set(gpriv, status); |
1080 | if (!(usbhsg_status_has(gpriv, USBHSG_STATUS_STARTED) && | 643 | if (!(usbhsg_status_has(gpriv, USBHSG_STATUS_STARTED) && |
1081 | usbhsg_status_has(gpriv, USBHSG_STATUS_REGISTERD))) | 644 | usbhsg_status_has(gpriv, USBHSG_STATUS_REGISTERD))) |
1082 | goto usbhsg_try_start_unlock; | 645 | ret = -1; /* not ready */ |
646 | |||
647 | usbhs_unlock(priv, flags); | ||
648 | /******************** spin unlock ********************/ | ||
649 | |||
650 | if (ret < 0) | ||
651 | return 0; /* not ready is not error */ | ||
1083 | 652 | ||
653 | /* | ||
654 | * enable interrupt and systems if ready | ||
655 | */ | ||
1084 | dev_dbg(dev, "start gadget\n"); | 656 | dev_dbg(dev, "start gadget\n"); |
1085 | 657 | ||
1086 | /* | 658 | /* |
1087 | * pipe initialize and enable DCP | 659 | * pipe initialize and enable DCP |
1088 | */ | 660 | */ |
1089 | usbhs_pipe_init(priv); | 661 | usbhs_pipe_init(priv, |
662 | usbhsg_queue_done, | ||
663 | usbhsg_dma_map_ctrl); | ||
664 | usbhs_fifo_init(priv); | ||
1090 | usbhsg_uep_init(gpriv); | 665 | usbhsg_uep_init(gpriv); |
1091 | usbhsg_dcp_enable(dcp); | 666 | |
667 | /* dcp init */ | ||
668 | dcp->pipe = usbhs_dcp_malloc(priv); | ||
669 | dcp->pipe->mod_private = dcp; | ||
1092 | 670 | ||
1093 | /* | 671 | /* |
1094 | * system config enble | 672 | * system config enble |
@@ -1105,16 +683,8 @@ static int usbhsg_try_start(struct usbhs_priv *priv, u32 status) | |||
1105 | */ | 683 | */ |
1106 | mod->irq_dev_state = usbhsg_irq_dev_state; | 684 | mod->irq_dev_state = usbhsg_irq_dev_state; |
1107 | mod->irq_ctrl_stage = usbhsg_irq_ctrl_stage; | 685 | mod->irq_ctrl_stage = usbhsg_irq_ctrl_stage; |
1108 | mod->irq_empty = usbhsg_irq_empty; | ||
1109 | mod->irq_ready = usbhsg_irq_ready; | ||
1110 | mod->irq_bempsts = 0; | ||
1111 | mod->irq_brdysts = 0; | ||
1112 | usbhs_irq_callback_update(priv, mod); | 686 | usbhs_irq_callback_update(priv, mod); |
1113 | 687 | ||
1114 | usbhsg_try_start_unlock: | ||
1115 | usbhsg_unlock(lock, &flags); | ||
1116 | /******************** spin unlock ********************/ | ||
1117 | |||
1118 | return 0; | 688 | return 0; |
1119 | } | 689 | } |
1120 | 690 | ||
@@ -1124,31 +694,33 @@ static int usbhsg_try_stop(struct usbhs_priv *priv, u32 status) | |||
1124 | struct usbhs_mod *mod = usbhs_mod_get_current(priv); | 694 | struct usbhs_mod *mod = usbhs_mod_get_current(priv); |
1125 | struct usbhsg_uep *dcp = usbhsg_gpriv_to_dcp(gpriv); | 695 | struct usbhsg_uep *dcp = usbhsg_gpriv_to_dcp(gpriv); |
1126 | struct device *dev = usbhs_priv_to_dev(priv); | 696 | struct device *dev = usbhs_priv_to_dev(priv); |
1127 | spinlock_t *lock; | ||
1128 | unsigned long flags; | 697 | unsigned long flags; |
698 | int ret = 0; | ||
1129 | 699 | ||
1130 | /******************** spin lock ********************/ | 700 | /******************** spin lock ********************/ |
1131 | lock = usbhsg_trylock(gpriv, &flags); | 701 | usbhs_lock(priv, flags); |
1132 | 702 | ||
1133 | /* | ||
1134 | * disable interrupt and systems if 1st try | ||
1135 | */ | ||
1136 | usbhsg_status_clr(gpriv, status); | 703 | usbhsg_status_clr(gpriv, status); |
1137 | if (!usbhsg_status_has(gpriv, USBHSG_STATUS_STARTED) && | 704 | if (!usbhsg_status_has(gpriv, USBHSG_STATUS_STARTED) && |
1138 | !usbhsg_status_has(gpriv, USBHSG_STATUS_REGISTERD)) | 705 | !usbhsg_status_has(gpriv, USBHSG_STATUS_REGISTERD)) |
1139 | goto usbhsg_try_stop_unlock; | 706 | ret = -1; /* already done */ |
707 | |||
708 | usbhs_unlock(priv, flags); | ||
709 | /******************** spin unlock ********************/ | ||
710 | |||
711 | if (ret < 0) | ||
712 | return 0; /* already done is not error */ | ||
713 | |||
714 | /* | ||
715 | * disable interrupt and systems if 1st try | ||
716 | */ | ||
717 | usbhs_fifo_quit(priv); | ||
1140 | 718 | ||
1141 | /* disable all irq */ | 719 | /* disable all irq */ |
1142 | mod->irq_dev_state = NULL; | 720 | mod->irq_dev_state = NULL; |
1143 | mod->irq_ctrl_stage = NULL; | 721 | mod->irq_ctrl_stage = NULL; |
1144 | mod->irq_empty = NULL; | ||
1145 | mod->irq_ready = NULL; | ||
1146 | mod->irq_bempsts = 0; | ||
1147 | mod->irq_brdysts = 0; | ||
1148 | usbhs_irq_callback_update(priv, mod); | 722 | usbhs_irq_callback_update(priv, mod); |
1149 | 723 | ||
1150 | usbhsg_dcp_disable(dcp); | ||
1151 | |||
1152 | gpriv->gadget.speed = USB_SPEED_UNKNOWN; | 724 | gpriv->gadget.speed = USB_SPEED_UNKNOWN; |
1153 | 725 | ||
1154 | /* disable sys */ | 726 | /* disable sys */ |
@@ -1156,8 +728,7 @@ static int usbhsg_try_stop(struct usbhs_priv *priv, u32 status) | |||
1156 | usbhs_sys_function_ctrl(priv, 0); | 728 | usbhs_sys_function_ctrl(priv, 0); |
1157 | usbhs_sys_usb_ctrl(priv, 0); | 729 | usbhs_sys_usb_ctrl(priv, 0); |
1158 | 730 | ||
1159 | usbhsg_unlock(lock, &flags); | 731 | usbhsg_pipe_disable(dcp); |
1160 | /******************** spin unlock ********************/ | ||
1161 | 732 | ||
1162 | if (gpriv->driver && | 733 | if (gpriv->driver && |
1163 | gpriv->driver->disconnect) | 734 | gpriv->driver->disconnect) |
@@ -1166,11 +737,6 @@ static int usbhsg_try_stop(struct usbhs_priv *priv, u32 status) | |||
1166 | dev_dbg(dev, "stop gadget\n"); | 737 | dev_dbg(dev, "stop gadget\n"); |
1167 | 738 | ||
1168 | return 0; | 739 | return 0; |
1169 | |||
1170 | usbhsg_try_stop_unlock: | ||
1171 | usbhsg_unlock(lock, &flags); | ||
1172 | |||
1173 | return 0; | ||
1174 | } | 740 | } |
1175 | 741 | ||
1176 | /* | 742 | /* |
@@ -1178,11 +744,10 @@ usbhsg_try_stop_unlock: | |||
1178 | * linux usb function | 744 | * linux usb function |
1179 | * | 745 | * |
1180 | */ | 746 | */ |
1181 | struct usbhsg_gpriv *the_controller; | 747 | static int usbhsg_gadget_start(struct usb_gadget_driver *driver, |
1182 | int usb_gadget_probe_driver(struct usb_gadget_driver *driver, | ||
1183 | int (*bind)(struct usb_gadget *)) | 748 | int (*bind)(struct usb_gadget *)) |
1184 | { | 749 | { |
1185 | struct usbhsg_gpriv *gpriv = the_controller; | 750 | struct usbhsg_gpriv *gpriv; |
1186 | struct usbhs_priv *priv; | 751 | struct usbhs_priv *priv; |
1187 | struct device *dev; | 752 | struct device *dev; |
1188 | int ret; | 753 | int ret; |
@@ -1192,10 +757,17 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver, | |||
1192 | !driver->setup || | 757 | !driver->setup || |
1193 | driver->speed != USB_SPEED_HIGH) | 758 | driver->speed != USB_SPEED_HIGH) |
1194 | return -EINVAL; | 759 | return -EINVAL; |
1195 | if (!gpriv) | 760 | |
1196 | return -ENODEV; | 761 | /* |
1197 | if (gpriv->driver) | 762 | * find unused controller |
1198 | return -EBUSY; | 763 | */ |
764 | usbhsg_for_each_controller(gpriv) { | ||
765 | if (!gpriv->driver) | ||
766 | goto find_unused_controller; | ||
767 | } | ||
768 | return -ENODEV; | ||
769 | |||
770 | find_unused_controller: | ||
1199 | 771 | ||
1200 | dev = usbhsg_gpriv_to_dev(gpriv); | 772 | dev = usbhsg_gpriv_to_dev(gpriv); |
1201 | priv = usbhsg_gpriv_to_priv(gpriv); | 773 | priv = usbhsg_gpriv_to_priv(gpriv); |
@@ -1229,22 +801,28 @@ add_fail: | |||
1229 | 801 | ||
1230 | return ret; | 802 | return ret; |
1231 | } | 803 | } |
1232 | EXPORT_SYMBOL(usb_gadget_probe_driver); | ||
1233 | 804 | ||
1234 | int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) | 805 | static int usbhsg_gadget_stop(struct usb_gadget_driver *driver) |
1235 | { | 806 | { |
1236 | struct usbhsg_gpriv *gpriv = the_controller; | 807 | struct usbhsg_gpriv *gpriv; |
1237 | struct usbhs_priv *priv; | 808 | struct usbhs_priv *priv; |
1238 | struct device *dev = usbhsg_gpriv_to_dev(gpriv); | 809 | struct device *dev; |
1239 | |||
1240 | if (!gpriv) | ||
1241 | return -ENODEV; | ||
1242 | 810 | ||
1243 | if (!driver || | 811 | if (!driver || |
1244 | !driver->unbind || | 812 | !driver->unbind) |
1245 | driver != gpriv->driver) | ||
1246 | return -EINVAL; | 813 | return -EINVAL; |
1247 | 814 | ||
815 | /* | ||
816 | * find controller | ||
817 | */ | ||
818 | usbhsg_for_each_controller(gpriv) { | ||
819 | if (gpriv->driver == driver) | ||
820 | goto find_matching_controller; | ||
821 | } | ||
822 | return -ENODEV; | ||
823 | |||
824 | find_matching_controller: | ||
825 | |||
1248 | dev = usbhsg_gpriv_to_dev(gpriv); | 826 | dev = usbhsg_gpriv_to_dev(gpriv); |
1249 | priv = usbhsg_gpriv_to_priv(gpriv); | 827 | priv = usbhsg_gpriv_to_priv(gpriv); |
1250 | 828 | ||
@@ -1260,7 +838,6 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) | |||
1260 | 838 | ||
1261 | return 0; | 839 | return 0; |
1262 | } | 840 | } |
1263 | EXPORT_SYMBOL(usb_gadget_unregister_driver); | ||
1264 | 841 | ||
1265 | /* | 842 | /* |
1266 | * usb gadget ops | 843 | * usb gadget ops |
@@ -1275,6 +852,8 @@ static int usbhsg_get_frame(struct usb_gadget *gadget) | |||
1275 | 852 | ||
1276 | static struct usb_gadget_ops usbhsg_gadget_ops = { | 853 | static struct usb_gadget_ops usbhsg_gadget_ops = { |
1277 | .get_frame = usbhsg_get_frame, | 854 | .get_frame = usbhsg_get_frame, |
855 | .start = usbhsg_gadget_start, | ||
856 | .stop = usbhsg_gadget_stop, | ||
1278 | }; | 857 | }; |
1279 | 858 | ||
1280 | static int usbhsg_start(struct usbhs_priv *priv) | 859 | static int usbhsg_start(struct usbhs_priv *priv) |
@@ -1294,6 +873,7 @@ int __devinit usbhs_mod_gadget_probe(struct usbhs_priv *priv) | |||
1294 | struct device *dev = usbhs_priv_to_dev(priv); | 873 | struct device *dev = usbhs_priv_to_dev(priv); |
1295 | int pipe_size = usbhs_get_dparam(priv, pipe_size); | 874 | int pipe_size = usbhs_get_dparam(priv, pipe_size); |
1296 | int i; | 875 | int i; |
876 | int ret; | ||
1297 | 877 | ||
1298 | gpriv = kzalloc(sizeof(struct usbhsg_gpriv), GFP_KERNEL); | 878 | gpriv = kzalloc(sizeof(struct usbhsg_gpriv), GFP_KERNEL); |
1299 | if (!gpriv) { | 879 | if (!gpriv) { |
@@ -1304,6 +884,7 @@ int __devinit usbhs_mod_gadget_probe(struct usbhs_priv *priv) | |||
1304 | uep = kzalloc(sizeof(struct usbhsg_uep) * pipe_size, GFP_KERNEL); | 884 | uep = kzalloc(sizeof(struct usbhsg_uep) * pipe_size, GFP_KERNEL); |
1305 | if (!uep) { | 885 | if (!uep) { |
1306 | dev_err(dev, "Could not allocate ep\n"); | 886 | dev_err(dev, "Could not allocate ep\n"); |
887 | ret = -ENOMEM; | ||
1307 | goto usbhs_mod_gadget_probe_err_gpriv; | 888 | goto usbhs_mod_gadget_probe_err_gpriv; |
1308 | } | 889 | } |
1309 | 890 | ||
@@ -1350,7 +931,6 @@ int __devinit usbhs_mod_gadget_probe(struct usbhs_priv *priv) | |||
1350 | uep->ep.name = uep->ep_name; | 931 | uep->ep.name = uep->ep_name; |
1351 | uep->ep.ops = &usbhsg_ep_ops; | 932 | uep->ep.ops = &usbhsg_ep_ops; |
1352 | INIT_LIST_HEAD(&uep->ep.ep_list); | 933 | INIT_LIST_HEAD(&uep->ep.ep_list); |
1353 | INIT_LIST_HEAD(&uep->list); | ||
1354 | 934 | ||
1355 | /* init DCP */ | 935 | /* init DCP */ |
1356 | if (usbhsg_is_dcp(uep)) { | 936 | if (usbhsg_is_dcp(uep)) { |
@@ -1364,22 +944,33 @@ int __devinit usbhs_mod_gadget_probe(struct usbhs_priv *priv) | |||
1364 | } | 944 | } |
1365 | } | 945 | } |
1366 | 946 | ||
1367 | the_controller = gpriv; | 947 | usbhsg_controller_register(gpriv); |
948 | |||
949 | ret = usb_add_gadget_udc(dev, &gpriv->gadget); | ||
950 | if (ret) | ||
951 | goto err_add_udc; | ||
952 | |||
1368 | 953 | ||
1369 | dev_info(dev, "gadget probed\n"); | 954 | dev_info(dev, "gadget probed\n"); |
1370 | 955 | ||
1371 | return 0; | 956 | return 0; |
957 | err_add_udc: | ||
958 | kfree(gpriv->uep); | ||
1372 | 959 | ||
1373 | usbhs_mod_gadget_probe_err_gpriv: | 960 | usbhs_mod_gadget_probe_err_gpriv: |
1374 | kfree(gpriv); | 961 | kfree(gpriv); |
1375 | 962 | ||
1376 | return -ENOMEM; | 963 | return ret; |
1377 | } | 964 | } |
1378 | 965 | ||
1379 | void __devexit usbhs_mod_gadget_remove(struct usbhs_priv *priv) | 966 | void __devexit usbhs_mod_gadget_remove(struct usbhs_priv *priv) |
1380 | { | 967 | { |
1381 | struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); | 968 | struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); |
1382 | 969 | ||
970 | usb_del_gadget_udc(&gpriv->gadget); | ||
971 | |||
972 | usbhsg_controller_unregister(gpriv); | ||
973 | |||
1383 | kfree(gpriv->uep); | 974 | kfree(gpriv->uep); |
1384 | kfree(gpriv); | 975 | kfree(gpriv); |
1385 | } | 976 | } |
diff --git a/drivers/usb/renesas_usbhs/pipe.c b/drivers/usb/renesas_usbhs/pipe.c index bc4521c5426..1b14cae4570 100644 --- a/drivers/usb/renesas_usbhs/pipe.c +++ b/drivers/usb/renesas_usbhs/pipe.c | |||
@@ -15,7 +15,6 @@ | |||
15 | * | 15 | * |
16 | */ | 16 | */ |
17 | #include <linux/delay.h> | 17 | #include <linux/delay.h> |
18 | #include <linux/io.h> | ||
19 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
20 | #include "./common.h" | 19 | #include "./common.h" |
21 | #include "./pipe.h" | 20 | #include "./pipe.h" |
@@ -23,13 +22,8 @@ | |||
23 | /* | 22 | /* |
24 | * macros | 23 | * macros |
25 | */ | 24 | */ |
26 | #define usbhsp_priv_to_pipeinfo(pr) (&(pr)->pipe_info) | ||
27 | #define usbhsp_pipe_to_priv(p) ((p)->priv) | ||
28 | |||
29 | #define usbhsp_addr_offset(p) ((usbhs_pipe_number(p) - 1) * 2) | 25 | #define usbhsp_addr_offset(p) ((usbhs_pipe_number(p) - 1) * 2) |
30 | 26 | ||
31 | #define usbhsp_is_dcp(p) ((p)->priv->pipe_info.pipe == (p)) | ||
32 | |||
33 | #define usbhsp_flags_set(p, f) ((p)->flags |= USBHS_PIPE_FLAGS_##f) | 27 | #define usbhsp_flags_set(p, f) ((p)->flags |= USBHS_PIPE_FLAGS_##f) |
34 | #define usbhsp_flags_clr(p, f) ((p)->flags &= ~USBHS_PIPE_FLAGS_##f) | 28 | #define usbhsp_flags_clr(p, f) ((p)->flags &= ~USBHS_PIPE_FLAGS_##f) |
35 | #define usbhsp_flags_has(p, f) ((p)->flags & USBHS_PIPE_FLAGS_##f) | 29 | #define usbhsp_flags_has(p, f) ((p)->flags & USBHS_PIPE_FLAGS_##f) |
@@ -77,10 +71,10 @@ void usbhs_usbreq_set_val(struct usbhs_priv *priv, struct usb_ctrlrequest *req) | |||
77 | */ | 71 | */ |
78 | static void usbhsp_pipectrl_set(struct usbhs_pipe *pipe, u16 mask, u16 val) | 72 | static void usbhsp_pipectrl_set(struct usbhs_pipe *pipe, u16 mask, u16 val) |
79 | { | 73 | { |
80 | struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe); | 74 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); |
81 | int offset = usbhsp_addr_offset(pipe); | 75 | int offset = usbhsp_addr_offset(pipe); |
82 | 76 | ||
83 | if (usbhsp_is_dcp(pipe)) | 77 | if (usbhs_pipe_is_dcp(pipe)) |
84 | usbhs_bset(priv, DCPCTR, mask, val); | 78 | usbhs_bset(priv, DCPCTR, mask, val); |
85 | else | 79 | else |
86 | usbhs_bset(priv, PIPEnCTR + offset, mask, val); | 80 | usbhs_bset(priv, PIPEnCTR + offset, mask, val); |
@@ -88,10 +82,10 @@ static void usbhsp_pipectrl_set(struct usbhs_pipe *pipe, u16 mask, u16 val) | |||
88 | 82 | ||
89 | static u16 usbhsp_pipectrl_get(struct usbhs_pipe *pipe) | 83 | static u16 usbhsp_pipectrl_get(struct usbhs_pipe *pipe) |
90 | { | 84 | { |
91 | struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe); | 85 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); |
92 | int offset = usbhsp_addr_offset(pipe); | 86 | int offset = usbhsp_addr_offset(pipe); |
93 | 87 | ||
94 | if (usbhsp_is_dcp(pipe)) | 88 | if (usbhs_pipe_is_dcp(pipe)) |
95 | return usbhs_read(priv, DCPCTR); | 89 | return usbhs_read(priv, DCPCTR); |
96 | else | 90 | else |
97 | return usbhs_read(priv, PIPEnCTR + offset); | 91 | return usbhs_read(priv, PIPEnCTR + offset); |
@@ -104,9 +98,9 @@ static void __usbhsp_pipe_xxx_set(struct usbhs_pipe *pipe, | |||
104 | u16 dcp_reg, u16 pipe_reg, | 98 | u16 dcp_reg, u16 pipe_reg, |
105 | u16 mask, u16 val) | 99 | u16 mask, u16 val) |
106 | { | 100 | { |
107 | struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe); | 101 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); |
108 | 102 | ||
109 | if (usbhsp_is_dcp(pipe)) | 103 | if (usbhs_pipe_is_dcp(pipe)) |
110 | usbhs_bset(priv, dcp_reg, mask, val); | 104 | usbhs_bset(priv, dcp_reg, mask, val); |
111 | else | 105 | else |
112 | usbhs_bset(priv, pipe_reg, mask, val); | 106 | usbhs_bset(priv, pipe_reg, mask, val); |
@@ -115,9 +109,9 @@ static void __usbhsp_pipe_xxx_set(struct usbhs_pipe *pipe, | |||
115 | static u16 __usbhsp_pipe_xxx_get(struct usbhs_pipe *pipe, | 109 | static u16 __usbhsp_pipe_xxx_get(struct usbhs_pipe *pipe, |
116 | u16 dcp_reg, u16 pipe_reg) | 110 | u16 dcp_reg, u16 pipe_reg) |
117 | { | 111 | { |
118 | struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe); | 112 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); |
119 | 113 | ||
120 | if (usbhsp_is_dcp(pipe)) | 114 | if (usbhs_pipe_is_dcp(pipe)) |
121 | return usbhs_read(priv, dcp_reg); | 115 | return usbhs_read(priv, dcp_reg); |
122 | else | 116 | else |
123 | return usbhs_read(priv, pipe_reg); | 117 | return usbhs_read(priv, pipe_reg); |
@@ -136,7 +130,7 @@ static void usbhsp_pipe_cfg_set(struct usbhs_pipe *pipe, u16 mask, u16 val) | |||
136 | */ | 130 | */ |
137 | static void usbhsp_pipe_buf_set(struct usbhs_pipe *pipe, u16 mask, u16 val) | 131 | static void usbhsp_pipe_buf_set(struct usbhs_pipe *pipe, u16 mask, u16 val) |
138 | { | 132 | { |
139 | if (usbhsp_is_dcp(pipe)) | 133 | if (usbhs_pipe_is_dcp(pipe)) |
140 | return; | 134 | return; |
141 | 135 | ||
142 | __usbhsp_pipe_xxx_set(pipe, 0, PIPEBUF, mask, val); | 136 | __usbhsp_pipe_xxx_set(pipe, 0, PIPEBUF, mask, val); |
@@ -160,7 +154,7 @@ static u16 usbhsp_pipe_maxp_get(struct usbhs_pipe *pipe) | |||
160 | */ | 154 | */ |
161 | static void usbhsp_pipe_select(struct usbhs_pipe *pipe) | 155 | static void usbhsp_pipe_select(struct usbhs_pipe *pipe) |
162 | { | 156 | { |
163 | struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe); | 157 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); |
164 | 158 | ||
165 | /* | 159 | /* |
166 | * On pipe, this is necessary before | 160 | * On pipe, this is necessary before |
@@ -182,7 +176,7 @@ static void usbhsp_pipe_select(struct usbhs_pipe *pipe) | |||
182 | 176 | ||
183 | static int usbhsp_pipe_barrier(struct usbhs_pipe *pipe) | 177 | static int usbhsp_pipe_barrier(struct usbhs_pipe *pipe) |
184 | { | 178 | { |
185 | struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe); | 179 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); |
186 | int timeout = 1024; | 180 | int timeout = 1024; |
187 | u16 val; | 181 | u16 val; |
188 | 182 | ||
@@ -205,7 +199,7 @@ static int usbhsp_pipe_barrier(struct usbhs_pipe *pipe) | |||
205 | * - "Pipe Control Registers Switching Procedure" | 199 | * - "Pipe Control Registers Switching Procedure" |
206 | */ | 200 | */ |
207 | usbhs_write(priv, CFIFOSEL, 0); | 201 | usbhs_write(priv, CFIFOSEL, 0); |
208 | usbhs_fifo_disable(pipe); | 202 | usbhs_pipe_disable(pipe); |
209 | 203 | ||
210 | do { | 204 | do { |
211 | val = usbhsp_pipectrl_get(pipe); | 205 | val = usbhsp_pipectrl_get(pipe); |
@@ -220,7 +214,7 @@ static int usbhsp_pipe_barrier(struct usbhs_pipe *pipe) | |||
220 | return -EBUSY; | 214 | return -EBUSY; |
221 | } | 215 | } |
222 | 216 | ||
223 | static int usbhsp_pipe_is_accessible(struct usbhs_pipe *pipe) | 217 | int usbhs_pipe_is_accessible(struct usbhs_pipe *pipe) |
224 | { | 218 | { |
225 | u16 val; | 219 | u16 val; |
226 | 220 | ||
@@ -253,7 +247,7 @@ static void __usbhsp_pid_try_nak_if_stall(struct usbhs_pipe *pipe) | |||
253 | } | 247 | } |
254 | } | 248 | } |
255 | 249 | ||
256 | void usbhs_fifo_disable(struct usbhs_pipe *pipe) | 250 | void usbhs_pipe_disable(struct usbhs_pipe *pipe) |
257 | { | 251 | { |
258 | int timeout = 1024; | 252 | int timeout = 1024; |
259 | u16 val; | 253 | u16 val; |
@@ -273,7 +267,7 @@ void usbhs_fifo_disable(struct usbhs_pipe *pipe) | |||
273 | } while (timeout--); | 267 | } while (timeout--); |
274 | } | 268 | } |
275 | 269 | ||
276 | void usbhs_fifo_enable(struct usbhs_pipe *pipe) | 270 | void usbhs_pipe_enable(struct usbhs_pipe *pipe) |
277 | { | 271 | { |
278 | /* see "Pipe n Control Register" - "PID" */ | 272 | /* see "Pipe n Control Register" - "PID" */ |
279 | __usbhsp_pid_try_nak_if_stall(pipe); | 273 | __usbhsp_pid_try_nak_if_stall(pipe); |
@@ -281,7 +275,7 @@ void usbhs_fifo_enable(struct usbhs_pipe *pipe) | |||
281 | usbhsp_pipectrl_set(pipe, PID_MASK, PID_BUF); | 275 | usbhsp_pipectrl_set(pipe, PID_MASK, PID_BUF); |
282 | } | 276 | } |
283 | 277 | ||
284 | void usbhs_fifo_stall(struct usbhs_pipe *pipe) | 278 | void usbhs_pipe_stall(struct usbhs_pipe *pipe) |
285 | { | 279 | { |
286 | u16 pid = usbhsp_pipectrl_get(pipe); | 280 | u16 pid = usbhsp_pipectrl_get(pipe); |
287 | 281 | ||
@@ -302,191 +296,6 @@ void usbhs_fifo_stall(struct usbhs_pipe *pipe) | |||
302 | } | 296 | } |
303 | 297 | ||
304 | /* | 298 | /* |
305 | * CFIFO ctrl | ||
306 | */ | ||
307 | void usbhs_fifo_send_terminator(struct usbhs_pipe *pipe) | ||
308 | { | ||
309 | struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe); | ||
310 | |||
311 | usbhs_bset(priv, CFIFOCTR, BVAL, BVAL); | ||
312 | } | ||
313 | |||
314 | static void usbhsp_fifo_clear(struct usbhs_pipe *pipe) | ||
315 | { | ||
316 | struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe); | ||
317 | |||
318 | usbhs_write(priv, CFIFOCTR, BCLR); | ||
319 | } | ||
320 | |||
321 | static int usbhsp_fifo_barrier(struct usbhs_priv *priv) | ||
322 | { | ||
323 | int timeout = 1024; | ||
324 | |||
325 | do { | ||
326 | /* The FIFO port is accessible */ | ||
327 | if (usbhs_read(priv, CFIFOCTR) & FRDY) | ||
328 | return 0; | ||
329 | |||
330 | udelay(10); | ||
331 | } while (timeout--); | ||
332 | |||
333 | return -EBUSY; | ||
334 | } | ||
335 | |||
336 | static int usbhsp_fifo_rcv_len(struct usbhs_priv *priv) | ||
337 | { | ||
338 | return usbhs_read(priv, CFIFOCTR) & DTLN_MASK; | ||
339 | } | ||
340 | |||
341 | static int usbhsp_fifo_select(struct usbhs_pipe *pipe, int write) | ||
342 | { | ||
343 | struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe); | ||
344 | struct device *dev = usbhs_priv_to_dev(priv); | ||
345 | int timeout = 1024; | ||
346 | u16 mask = ((1 << 5) | 0xF); /* mask of ISEL | CURPIPE */ | ||
347 | u16 base = usbhs_pipe_number(pipe); /* CURPIPE */ | ||
348 | |||
349 | if (usbhsp_is_dcp(pipe)) | ||
350 | base |= (1 == write) << 5; /* ISEL */ | ||
351 | |||
352 | /* "base" will be used below */ | ||
353 | usbhs_write(priv, CFIFOSEL, base | MBW_32); | ||
354 | |||
355 | /* check ISEL and CURPIPE value */ | ||
356 | while (timeout--) { | ||
357 | if (base == (mask & usbhs_read(priv, CFIFOSEL))) | ||
358 | return 0; | ||
359 | udelay(10); | ||
360 | } | ||
361 | |||
362 | dev_err(dev, "fifo select error\n"); | ||
363 | |||
364 | return -EIO; | ||
365 | } | ||
366 | |||
367 | int usbhs_fifo_prepare_write(struct usbhs_pipe *pipe) | ||
368 | { | ||
369 | return usbhsp_fifo_select(pipe, 1); | ||
370 | } | ||
371 | |||
372 | int usbhs_fifo_write(struct usbhs_pipe *pipe, u8 *buf, int len) | ||
373 | { | ||
374 | struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe); | ||
375 | void __iomem *addr = priv->base + CFIFO; | ||
376 | int maxp = usbhs_pipe_get_maxpacket(pipe); | ||
377 | int total_len; | ||
378 | int i, ret; | ||
379 | |||
380 | ret = usbhsp_pipe_is_accessible(pipe); | ||
381 | if (ret < 0) | ||
382 | return ret; | ||
383 | |||
384 | ret = usbhsp_fifo_select(pipe, 1); | ||
385 | if (ret < 0) | ||
386 | return ret; | ||
387 | |||
388 | ret = usbhsp_fifo_barrier(priv); | ||
389 | if (ret < 0) | ||
390 | return ret; | ||
391 | |||
392 | len = min(len, maxp); | ||
393 | total_len = len; | ||
394 | |||
395 | /* | ||
396 | * FIXME | ||
397 | * | ||
398 | * 32-bit access only | ||
399 | */ | ||
400 | if (len >= 4 && | ||
401 | !((unsigned long)buf & 0x03)) { | ||
402 | iowrite32_rep(addr, buf, len / 4); | ||
403 | len %= 4; | ||
404 | buf += total_len - len; | ||
405 | } | ||
406 | |||
407 | /* the rest operation */ | ||
408 | for (i = 0; i < len; i++) | ||
409 | iowrite8(buf[i], addr + (0x03 - (i & 0x03))); | ||
410 | |||
411 | if (total_len < maxp) | ||
412 | usbhs_fifo_send_terminator(pipe); | ||
413 | |||
414 | return total_len; | ||
415 | } | ||
416 | |||
417 | int usbhs_fifo_prepare_read(struct usbhs_pipe *pipe) | ||
418 | { | ||
419 | int ret; | ||
420 | |||
421 | /* | ||
422 | * select pipe and enable it to prepare packet receive | ||
423 | */ | ||
424 | ret = usbhsp_fifo_select(pipe, 0); | ||
425 | if (ret < 0) | ||
426 | return ret; | ||
427 | |||
428 | usbhs_fifo_enable(pipe); | ||
429 | |||
430 | return ret; | ||
431 | } | ||
432 | |||
433 | int usbhs_fifo_read(struct usbhs_pipe *pipe, u8 *buf, int len) | ||
434 | { | ||
435 | struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe); | ||
436 | void __iomem *addr = priv->base + CFIFO; | ||
437 | int rcv_len; | ||
438 | int i, ret; | ||
439 | int total_len; | ||
440 | u32 data = 0; | ||
441 | |||
442 | ret = usbhsp_fifo_select(pipe, 0); | ||
443 | if (ret < 0) | ||
444 | return ret; | ||
445 | |||
446 | ret = usbhsp_fifo_barrier(priv); | ||
447 | if (ret < 0) | ||
448 | return ret; | ||
449 | |||
450 | rcv_len = usbhsp_fifo_rcv_len(priv); | ||
451 | |||
452 | /* | ||
453 | * Buffer clear if Zero-Length packet | ||
454 | * | ||
455 | * see | ||
456 | * "Operation" - "FIFO Buffer Memory" - "FIFO Port Function" | ||
457 | */ | ||
458 | if (0 == rcv_len) { | ||
459 | usbhsp_fifo_clear(pipe); | ||
460 | return 0; | ||
461 | } | ||
462 | |||
463 | len = min(rcv_len, len); | ||
464 | total_len = len; | ||
465 | |||
466 | /* | ||
467 | * FIXME | ||
468 | * | ||
469 | * 32-bit access only | ||
470 | */ | ||
471 | if (len >= 4 && | ||
472 | !((unsigned long)buf & 0x03)) { | ||
473 | ioread32_rep(addr, buf, len / 4); | ||
474 | len %= 4; | ||
475 | buf += rcv_len - len; | ||
476 | } | ||
477 | |||
478 | /* the rest operation */ | ||
479 | for (i = 0; i < len; i++) { | ||
480 | if (!(i & 0x03)) | ||
481 | data = ioread32(addr); | ||
482 | |||
483 | buf[i] = (data >> ((i & 0x03) * 8)) & 0xff; | ||
484 | } | ||
485 | |||
486 | return total_len; | ||
487 | } | ||
488 | |||
489 | /* | ||
490 | * pipe setup | 299 | * pipe setup |
491 | */ | 300 | */ |
492 | static int usbhsp_possible_double_buffer(struct usbhs_pipe *pipe) | 301 | static int usbhsp_possible_double_buffer(struct usbhs_pipe *pipe) |
@@ -519,7 +328,7 @@ static u16 usbhsp_setup_pipecfg(struct usbhs_pipe *pipe, | |||
519 | }; | 328 | }; |
520 | int is_double = usbhsp_possible_double_buffer(pipe); | 329 | int is_double = usbhsp_possible_double_buffer(pipe); |
521 | 330 | ||
522 | if (usbhsp_is_dcp(pipe)) | 331 | if (usbhs_pipe_is_dcp(pipe)) |
523 | return -EINVAL; | 332 | return -EINVAL; |
524 | 333 | ||
525 | /* | 334 | /* |
@@ -550,12 +359,15 @@ static u16 usbhsp_setup_pipecfg(struct usbhs_pipe *pipe, | |||
550 | 359 | ||
551 | /* DIR */ | 360 | /* DIR */ |
552 | if (usb_endpoint_dir_in(desc)) | 361 | if (usb_endpoint_dir_in(desc)) |
553 | usbhsp_flags_set(pipe, IS_DIR_IN); | 362 | usbhsp_flags_set(pipe, IS_DIR_HOST); |
554 | 363 | ||
555 | if ((is_host && usb_endpoint_dir_out(desc)) || | 364 | if ((is_host && usb_endpoint_dir_out(desc)) || |
556 | (!is_host && usb_endpoint_dir_in(desc))) | 365 | (!is_host && usb_endpoint_dir_in(desc))) |
557 | dir |= DIR_OUT; | 366 | dir |= DIR_OUT; |
558 | 367 | ||
368 | if (!dir) | ||
369 | usbhsp_flags_set(pipe, IS_DIR_IN); | ||
370 | |||
559 | /* SHTNAK */ | 371 | /* SHTNAK */ |
560 | if (usbhsp_type_is(pipe, USB_ENDPOINT_XFER_BULK) && | 372 | if (usbhsp_type_is(pipe, USB_ENDPOINT_XFER_BULK) && |
561 | !dir) | 373 | !dir) |
@@ -587,8 +399,8 @@ static u16 usbhsp_setup_pipebuff(struct usbhs_pipe *pipe, | |||
587 | const struct usb_endpoint_descriptor *desc, | 399 | const struct usb_endpoint_descriptor *desc, |
588 | int is_host) | 400 | int is_host) |
589 | { | 401 | { |
590 | struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe); | 402 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); |
591 | struct usbhs_pipe_info *info = usbhsp_priv_to_pipeinfo(priv); | 403 | struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv); |
592 | struct device *dev = usbhs_priv_to_dev(priv); | 404 | struct device *dev = usbhs_priv_to_dev(priv); |
593 | int pipe_num = usbhs_pipe_number(pipe); | 405 | int pipe_num = usbhs_pipe_number(pipe); |
594 | int is_double = usbhsp_possible_double_buffer(pipe); | 406 | int is_double = usbhsp_possible_double_buffer(pipe); |
@@ -666,7 +478,7 @@ static u16 usbhsp_setup_pipebuff(struct usbhs_pipe *pipe, | |||
666 | */ | 478 | */ |
667 | int usbhs_pipe_get_maxpacket(struct usbhs_pipe *pipe) | 479 | int usbhs_pipe_get_maxpacket(struct usbhs_pipe *pipe) |
668 | { | 480 | { |
669 | u16 mask = usbhsp_is_dcp(pipe) ? DCP_MAXP_MASK : PIPE_MAXP_MASK; | 481 | u16 mask = usbhs_pipe_is_dcp(pipe) ? DCP_MAXP_MASK : PIPE_MAXP_MASK; |
670 | 482 | ||
671 | usbhsp_pipe_select(pipe); | 483 | usbhsp_pipe_select(pipe); |
672 | 484 | ||
@@ -678,11 +490,22 @@ int usbhs_pipe_is_dir_in(struct usbhs_pipe *pipe) | |||
678 | return usbhsp_flags_has(pipe, IS_DIR_IN); | 490 | return usbhsp_flags_has(pipe, IS_DIR_IN); |
679 | } | 491 | } |
680 | 492 | ||
493 | int usbhs_pipe_is_dir_host(struct usbhs_pipe *pipe) | ||
494 | { | ||
495 | return usbhsp_flags_has(pipe, IS_DIR_HOST); | ||
496 | } | ||
497 | |||
681 | void usbhs_pipe_clear_sequence(struct usbhs_pipe *pipe) | 498 | void usbhs_pipe_clear_sequence(struct usbhs_pipe *pipe) |
682 | { | 499 | { |
683 | usbhsp_pipectrl_set(pipe, SQCLR, SQCLR); | 500 | usbhsp_pipectrl_set(pipe, SQCLR, SQCLR); |
684 | } | 501 | } |
685 | 502 | ||
503 | void usbhs_pipe_clear(struct usbhs_pipe *pipe) | ||
504 | { | ||
505 | usbhsp_pipectrl_set(pipe, ACLRM, ACLRM); | ||
506 | usbhsp_pipectrl_set(pipe, ACLRM, 0); | ||
507 | } | ||
508 | |||
686 | static struct usbhs_pipe *usbhsp_get_pipe(struct usbhs_priv *priv, u32 type) | 509 | static struct usbhs_pipe *usbhsp_get_pipe(struct usbhs_priv *priv, u32 type) |
687 | { | 510 | { |
688 | struct usbhs_pipe *pos, *pipe; | 511 | struct usbhs_pipe *pos, *pipe; |
@@ -714,12 +537,20 @@ static struct usbhs_pipe *usbhsp_get_pipe(struct usbhs_priv *priv, u32 type) | |||
714 | return pipe; | 537 | return pipe; |
715 | } | 538 | } |
716 | 539 | ||
717 | void usbhs_pipe_init(struct usbhs_priv *priv) | 540 | void usbhs_pipe_init(struct usbhs_priv *priv, |
541 | void (*done)(struct usbhs_pkt *pkt), | ||
542 | int (*dma_map_ctrl)(struct usbhs_pkt *pkt, int map)) | ||
718 | { | 543 | { |
719 | struct usbhs_pipe_info *info = usbhsp_priv_to_pipeinfo(priv); | 544 | struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv); |
545 | struct device *dev = usbhs_priv_to_dev(priv); | ||
720 | struct usbhs_pipe *pipe; | 546 | struct usbhs_pipe *pipe; |
721 | int i; | 547 | int i; |
722 | 548 | ||
549 | if (!done) { | ||
550 | dev_err(dev, "no done function\n"); | ||
551 | return; | ||
552 | } | ||
553 | |||
723 | /* | 554 | /* |
724 | * FIXME | 555 | * FIXME |
725 | * | 556 | * |
@@ -738,10 +569,16 @@ void usbhs_pipe_init(struct usbhs_priv *priv) | |||
738 | info->bufnmb_last++; | 569 | info->bufnmb_last++; |
739 | 570 | ||
740 | usbhsp_flags_init(pipe); | 571 | usbhsp_flags_init(pipe); |
572 | pipe->fifo = NULL; | ||
741 | pipe->mod_private = NULL; | 573 | pipe->mod_private = NULL; |
574 | INIT_LIST_HEAD(&pipe->list); | ||
742 | 575 | ||
743 | usbhsp_fifo_clear(pipe); | 576 | /* pipe force init */ |
577 | usbhs_pipe_clear(pipe); | ||
744 | } | 578 | } |
579 | |||
580 | info->done = done; | ||
581 | info->dma_map_ctrl = dma_map_ctrl; | ||
745 | } | 582 | } |
746 | 583 | ||
747 | struct usbhs_pipe *usbhs_pipe_malloc(struct usbhs_priv *priv, | 584 | struct usbhs_pipe *usbhs_pipe_malloc(struct usbhs_priv *priv, |
@@ -761,7 +598,9 @@ struct usbhs_pipe *usbhs_pipe_malloc(struct usbhs_priv *priv, | |||
761 | return NULL; | 598 | return NULL; |
762 | } | 599 | } |
763 | 600 | ||
764 | usbhs_fifo_disable(pipe); | 601 | INIT_LIST_HEAD(&pipe->list); |
602 | |||
603 | usbhs_pipe_disable(pipe); | ||
765 | 604 | ||
766 | /* make sure pipe is not busy */ | 605 | /* make sure pipe is not busy */ |
767 | ret = usbhsp_pipe_barrier(pipe); | 606 | ret = usbhsp_pipe_barrier(pipe); |
@@ -774,11 +613,6 @@ struct usbhs_pipe *usbhs_pipe_malloc(struct usbhs_priv *priv, | |||
774 | pipebuf = usbhsp_setup_pipebuff(pipe, desc, is_host); | 613 | pipebuf = usbhsp_setup_pipebuff(pipe, desc, is_host); |
775 | pipemaxp = usbhsp_setup_pipemaxp(pipe, desc, is_host); | 614 | pipemaxp = usbhsp_setup_pipemaxp(pipe, desc, is_host); |
776 | 615 | ||
777 | /* buffer clear | ||
778 | * see PIPECFG :: BFRE */ | ||
779 | usbhsp_pipectrl_set(pipe, ACLRM, ACLRM); | ||
780 | usbhsp_pipectrl_set(pipe, ACLRM, 0); | ||
781 | |||
782 | usbhsp_pipe_select(pipe); | 616 | usbhsp_pipe_select(pipe); |
783 | usbhsp_pipe_cfg_set(pipe, 0xFFFF, pipecfg); | 617 | usbhsp_pipe_cfg_set(pipe, 0xFFFF, pipecfg); |
784 | usbhsp_pipe_buf_set(pipe, 0xFFFF, pipebuf); | 618 | usbhsp_pipe_buf_set(pipe, 0xFFFF, pipebuf); |
@@ -794,6 +628,18 @@ struct usbhs_pipe *usbhs_pipe_malloc(struct usbhs_priv *priv, | |||
794 | return pipe; | 628 | return pipe; |
795 | } | 629 | } |
796 | 630 | ||
631 | void usbhs_pipe_select_fifo(struct usbhs_pipe *pipe, struct usbhs_fifo *fifo) | ||
632 | { | ||
633 | if (pipe->fifo) | ||
634 | pipe->fifo->pipe = NULL; | ||
635 | |||
636 | pipe->fifo = fifo; | ||
637 | |||
638 | if (fifo) | ||
639 | fifo->pipe = pipe; | ||
640 | } | ||
641 | |||
642 | |||
797 | /* | 643 | /* |
798 | * dcp control | 644 | * dcp control |
799 | */ | 645 | */ |
@@ -813,25 +659,25 @@ struct usbhs_pipe *usbhs_dcp_malloc(struct usbhs_priv *priv) | |||
813 | 659 | ||
814 | usbhsp_pipe_select(pipe); | 660 | usbhsp_pipe_select(pipe); |
815 | usbhs_pipe_clear_sequence(pipe); | 661 | usbhs_pipe_clear_sequence(pipe); |
662 | INIT_LIST_HEAD(&pipe->list); | ||
816 | 663 | ||
817 | return pipe; | 664 | return pipe; |
818 | } | 665 | } |
819 | 666 | ||
820 | void usbhs_dcp_control_transfer_done(struct usbhs_pipe *pipe) | 667 | void usbhs_dcp_control_transfer_done(struct usbhs_pipe *pipe) |
821 | { | 668 | { |
822 | WARN_ON(!usbhsp_is_dcp(pipe)); | 669 | WARN_ON(!usbhs_pipe_is_dcp(pipe)); |
823 | 670 | ||
824 | usbhs_fifo_enable(pipe); | 671 | usbhs_pipe_enable(pipe); |
825 | usbhsp_pipectrl_set(pipe, CCPL, CCPL); | 672 | usbhsp_pipectrl_set(pipe, CCPL, CCPL); |
826 | } | 673 | } |
827 | 674 | ||
828 | |||
829 | /* | 675 | /* |
830 | * pipe module function | 676 | * pipe module function |
831 | */ | 677 | */ |
832 | int usbhs_pipe_probe(struct usbhs_priv *priv) | 678 | int usbhs_pipe_probe(struct usbhs_priv *priv) |
833 | { | 679 | { |
834 | struct usbhs_pipe_info *info = usbhsp_priv_to_pipeinfo(priv); | 680 | struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv); |
835 | struct usbhs_pipe *pipe; | 681 | struct usbhs_pipe *pipe; |
836 | struct device *dev = usbhs_priv_to_dev(priv); | 682 | struct device *dev = usbhs_priv_to_dev(priv); |
837 | u32 *pipe_type = usbhs_get_dparam(priv, pipe_type); | 683 | u32 *pipe_type = usbhs_get_dparam(priv, pipe_type); |
@@ -868,7 +714,7 @@ int usbhs_pipe_probe(struct usbhs_priv *priv) | |||
868 | 714 | ||
869 | void usbhs_pipe_remove(struct usbhs_priv *priv) | 715 | void usbhs_pipe_remove(struct usbhs_priv *priv) |
870 | { | 716 | { |
871 | struct usbhs_pipe_info *info = usbhsp_priv_to_pipeinfo(priv); | 717 | struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv); |
872 | 718 | ||
873 | kfree(info->pipe); | 719 | kfree(info->pipe); |
874 | } | 720 | } |
diff --git a/drivers/usb/renesas_usbhs/pipe.h b/drivers/usb/renesas_usbhs/pipe.h index 1cca9b7fb26..41534cb0e73 100644 --- a/drivers/usb/renesas_usbhs/pipe.h +++ b/drivers/usb/renesas_usbhs/pipe.h | |||
@@ -18,6 +18,7 @@ | |||
18 | #define RENESAS_USB_PIPE_H | 18 | #define RENESAS_USB_PIPE_H |
19 | 19 | ||
20 | #include "./common.h" | 20 | #include "./common.h" |
21 | #include "./fifo.h" | ||
21 | 22 | ||
22 | /* | 23 | /* |
23 | * struct | 24 | * struct |
@@ -26,10 +27,13 @@ struct usbhs_pipe { | |||
26 | u32 pipe_type; /* USB_ENDPOINT_XFER_xxx */ | 27 | u32 pipe_type; /* USB_ENDPOINT_XFER_xxx */ |
27 | 28 | ||
28 | struct usbhs_priv *priv; | 29 | struct usbhs_priv *priv; |
30 | struct usbhs_fifo *fifo; | ||
31 | struct list_head list; | ||
29 | 32 | ||
30 | u32 flags; | 33 | u32 flags; |
31 | #define USBHS_PIPE_FLAGS_IS_USED (1 << 0) | 34 | #define USBHS_PIPE_FLAGS_IS_USED (1 << 0) |
32 | #define USBHS_PIPE_FLAGS_IS_DIR_IN (1 << 1) | 35 | #define USBHS_PIPE_FLAGS_IS_DIR_IN (1 << 1) |
36 | #define USBHS_PIPE_FLAGS_IS_DIR_HOST (1 << 2) | ||
33 | 37 | ||
34 | void *mod_private; | 38 | void *mod_private; |
35 | }; | 39 | }; |
@@ -38,6 +42,9 @@ struct usbhs_pipe_info { | |||
38 | struct usbhs_pipe *pipe; | 42 | struct usbhs_pipe *pipe; |
39 | int size; /* array size of "pipe" */ | 43 | int size; /* array size of "pipe" */ |
40 | int bufnmb_last; /* FIXME : driver needs good allocator */ | 44 | int bufnmb_last; /* FIXME : driver needs good allocator */ |
45 | |||
46 | void (*done)(struct usbhs_pkt *pkt); | ||
47 | int (*dma_map_ctrl)(struct usbhs_pkt *pkt, int map); | ||
41 | }; | 48 | }; |
42 | 49 | ||
43 | /* | 50 | /* |
@@ -55,25 +62,9 @@ struct usbhs_pipe_info { | |||
55 | __usbhs_for_each_pipe(0, pos, &((priv)->pipe_info), i) | 62 | __usbhs_for_each_pipe(0, pos, &((priv)->pipe_info), i) |
56 | 63 | ||
57 | /* | 64 | /* |
58 | * pipe module probe / remove | 65 | * data |
59 | */ | 66 | */ |
60 | int usbhs_pipe_probe(struct usbhs_priv *priv); | 67 | #define usbhs_priv_to_pipeinfo(pr) (&(pr)->pipe_info) |
61 | void usbhs_pipe_remove(struct usbhs_priv *priv); | ||
62 | |||
63 | /* | ||
64 | * cfifo | ||
65 | */ | ||
66 | int usbhs_fifo_write(struct usbhs_pipe *pipe, u8 *buf, int len); | ||
67 | int usbhs_fifo_read(struct usbhs_pipe *pipe, u8 *buf, int len); | ||
68 | int usbhs_fifo_prepare_write(struct usbhs_pipe *pipe); | ||
69 | int usbhs_fifo_prepare_read(struct usbhs_pipe *pipe); | ||
70 | |||
71 | void usbhs_fifo_enable(struct usbhs_pipe *pipe); | ||
72 | void usbhs_fifo_disable(struct usbhs_pipe *pipe); | ||
73 | void usbhs_fifo_stall(struct usbhs_pipe *pipe); | ||
74 | |||
75 | void usbhs_fifo_send_terminator(struct usbhs_pipe *pipe); | ||
76 | |||
77 | 68 | ||
78 | /* | 69 | /* |
79 | * usb request | 70 | * usb request |
@@ -87,13 +78,27 @@ void usbhs_usbreq_set_val(struct usbhs_priv *priv, struct usb_ctrlrequest *req); | |||
87 | struct usbhs_pipe | 78 | struct usbhs_pipe |
88 | *usbhs_pipe_malloc(struct usbhs_priv *priv, | 79 | *usbhs_pipe_malloc(struct usbhs_priv *priv, |
89 | const struct usb_endpoint_descriptor *desc); | 80 | const struct usb_endpoint_descriptor *desc); |
90 | 81 | int usbhs_pipe_probe(struct usbhs_priv *priv); | |
82 | void usbhs_pipe_remove(struct usbhs_priv *priv); | ||
91 | int usbhs_pipe_is_dir_in(struct usbhs_pipe *pipe); | 83 | int usbhs_pipe_is_dir_in(struct usbhs_pipe *pipe); |
92 | void usbhs_pipe_init(struct usbhs_priv *priv); | 84 | int usbhs_pipe_is_dir_host(struct usbhs_pipe *pipe); |
85 | void usbhs_pipe_init(struct usbhs_priv *priv, | ||
86 | void (*done)(struct usbhs_pkt *pkt), | ||
87 | int (*dma_map_ctrl)(struct usbhs_pkt *pkt, int map)); | ||
93 | int usbhs_pipe_get_maxpacket(struct usbhs_pipe *pipe); | 88 | int usbhs_pipe_get_maxpacket(struct usbhs_pipe *pipe); |
94 | void usbhs_pipe_clear_sequence(struct usbhs_pipe *pipe); | 89 | void usbhs_pipe_clear_sequence(struct usbhs_pipe *pipe); |
95 | 90 | void usbhs_pipe_clear(struct usbhs_pipe *pipe); | |
91 | int usbhs_pipe_is_accessible(struct usbhs_pipe *pipe); | ||
92 | void usbhs_pipe_enable(struct usbhs_pipe *pipe); | ||
93 | void usbhs_pipe_disable(struct usbhs_pipe *pipe); | ||
94 | void usbhs_pipe_stall(struct usbhs_pipe *pipe); | ||
95 | void usbhs_pipe_select_fifo(struct usbhs_pipe *pipe, struct usbhs_fifo *fifo); | ||
96 | |||
97 | #define usbhs_pipe_to_priv(p) ((p)->priv) | ||
96 | #define usbhs_pipe_number(p) (int)((p) - (p)->priv->pipe_info.pipe) | 98 | #define usbhs_pipe_number(p) (int)((p) - (p)->priv->pipe_info.pipe) |
99 | #define usbhs_pipe_is_dcp(p) ((p)->priv->pipe_info.pipe == (p)) | ||
100 | #define usbhs_pipe_to_fifo(p) ((p)->fifo) | ||
101 | #define usbhs_pipe_is_busy(p) usbhs_pipe_to_fifo(p) | ||
97 | 102 | ||
98 | /* | 103 | /* |
99 | * dcp control | 104 | * dcp control |