diff options
Diffstat (limited to 'drivers/usb/renesas_usbhs')
-rw-r--r-- | drivers/usb/renesas_usbhs/Kconfig | 2 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/Makefile | 8 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/common.c | 238 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/common.h | 60 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/fifo.c | 222 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/fifo.h | 22 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/mod.c | 81 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/mod.h | 61 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/mod_gadget.c | 134 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/mod_host.c | 1327 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/pipe.c | 200 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/pipe.h | 27 |
12 files changed, 2075 insertions, 307 deletions
diff --git a/drivers/usb/renesas_usbhs/Kconfig b/drivers/usb/renesas_usbhs/Kconfig index 286cbf1ca7de..6f4afa436381 100644 --- a/drivers/usb/renesas_usbhs/Kconfig +++ b/drivers/usb/renesas_usbhs/Kconfig | |||
@@ -4,7 +4,7 @@ | |||
4 | 4 | ||
5 | config USB_RENESAS_USBHS | 5 | config USB_RENESAS_USBHS |
6 | tristate 'Renesas USBHS controller' | 6 | tristate 'Renesas USBHS controller' |
7 | depends on SUPERH || ARCH_SHMOBILE | 7 | depends on USB && USB_GADGET |
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 |
diff --git a/drivers/usb/renesas_usbhs/Makefile b/drivers/usb/renesas_usbhs/Makefile index ce08345fa15a..bc8aef4311a1 100644 --- a/drivers/usb/renesas_usbhs/Makefile +++ b/drivers/usb/renesas_usbhs/Makefile | |||
@@ -6,4 +6,10 @@ obj-$(CONFIG_USB_RENESAS_USBHS) += renesas_usbhs.o | |||
6 | 6 | ||
7 | renesas_usbhs-y := common.o mod.o pipe.o fifo.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 | ifneq ($(CONFIG_USB_RENESAS_USBHS_HCD),) |
10 | renesas_usbhs-y += mod_host.o | ||
11 | endif | ||
12 | |||
13 | ifneq ($(CONFIG_USB_RENESAS_USBHS_UDC),) | ||
14 | renesas_usbhs-y += mod_gadget.o | ||
15 | endif | ||
diff --git a/drivers/usb/renesas_usbhs/common.c b/drivers/usb/renesas_usbhs/common.c index d8239e5efa66..08c679c0dde5 100644 --- a/drivers/usb/renesas_usbhs/common.c +++ b/drivers/usb/renesas_usbhs/common.c | |||
@@ -61,8 +61,8 @@ | |||
61 | */ | 61 | */ |
62 | #define usbhs_platform_call(priv, func, args...)\ | 62 | #define usbhs_platform_call(priv, func, args...)\ |
63 | (!(priv) ? -ENODEV : \ | 63 | (!(priv) ? -ENODEV : \ |
64 | !((priv)->pfunc->func) ? 0 : \ | 64 | !((priv)->pfunc.func) ? 0 : \ |
65 | (priv)->pfunc->func(args)) | 65 | (priv)->pfunc.func(args)) |
66 | 66 | ||
67 | /* | 67 | /* |
68 | * common functions | 68 | * common functions |
@@ -114,6 +114,10 @@ void usbhs_sys_host_ctrl(struct usbhs_priv *priv, int enable) | |||
114 | { | 114 | { |
115 | u16 mask = DCFM | DRPD | DPRPU; | 115 | u16 mask = DCFM | DRPD | DPRPU; |
116 | u16 val = DCFM | DRPD; | 116 | u16 val = DCFM | DRPD; |
117 | int has_otg = usbhs_get_dparam(priv, has_otg); | ||
118 | |||
119 | if (has_otg) | ||
120 | usbhs_bset(priv, DVSTCTR, (EXTLP | PWEN), (EXTLP | PWEN)); | ||
117 | 121 | ||
118 | /* | 122 | /* |
119 | * if enable | 123 | * if enable |
@@ -147,19 +151,133 @@ int usbhs_frame_get_num(struct usbhs_priv *priv) | |||
147 | } | 151 | } |
148 | 152 | ||
149 | /* | 153 | /* |
154 | * usb request functions | ||
155 | */ | ||
156 | void usbhs_usbreq_get_val(struct usbhs_priv *priv, struct usb_ctrlrequest *req) | ||
157 | { | ||
158 | u16 val; | ||
159 | |||
160 | val = usbhs_read(priv, USBREQ); | ||
161 | req->bRequest = (val >> 8) & 0xFF; | ||
162 | req->bRequestType = (val >> 0) & 0xFF; | ||
163 | |||
164 | req->wValue = usbhs_read(priv, USBVAL); | ||
165 | req->wIndex = usbhs_read(priv, USBINDX); | ||
166 | req->wLength = usbhs_read(priv, USBLENG); | ||
167 | } | ||
168 | |||
169 | void usbhs_usbreq_set_val(struct usbhs_priv *priv, struct usb_ctrlrequest *req) | ||
170 | { | ||
171 | usbhs_write(priv, USBREQ, (req->bRequest << 8) | req->bRequestType); | ||
172 | usbhs_write(priv, USBVAL, req->wValue); | ||
173 | usbhs_write(priv, USBINDX, req->wIndex); | ||
174 | usbhs_write(priv, USBLENG, req->wLength); | ||
175 | |||
176 | usbhs_bset(priv, DCPCTR, SUREQ, SUREQ); | ||
177 | } | ||
178 | |||
179 | /* | ||
180 | * bus/vbus functions | ||
181 | */ | ||
182 | void usbhs_bus_send_sof_enable(struct usbhs_priv *priv) | ||
183 | { | ||
184 | u16 status = usbhs_read(priv, DVSTCTR) & (USBRST | UACT); | ||
185 | |||
186 | if (status != USBRST) { | ||
187 | struct device *dev = usbhs_priv_to_dev(priv); | ||
188 | dev_err(dev, "usbhs should be reset\n"); | ||
189 | } | ||
190 | |||
191 | usbhs_bset(priv, DVSTCTR, (USBRST | UACT), UACT); | ||
192 | } | ||
193 | |||
194 | void usbhs_bus_send_reset(struct usbhs_priv *priv) | ||
195 | { | ||
196 | usbhs_bset(priv, DVSTCTR, (USBRST | UACT), USBRST); | ||
197 | } | ||
198 | |||
199 | int usbhs_bus_get_speed(struct usbhs_priv *priv) | ||
200 | { | ||
201 | u16 dvstctr = usbhs_read(priv, DVSTCTR); | ||
202 | |||
203 | switch (RHST & dvstctr) { | ||
204 | case RHST_LOW_SPEED: | ||
205 | return USB_SPEED_LOW; | ||
206 | case RHST_FULL_SPEED: | ||
207 | return USB_SPEED_FULL; | ||
208 | case RHST_HIGH_SPEED: | ||
209 | return USB_SPEED_HIGH; | ||
210 | } | ||
211 | |||
212 | return USB_SPEED_UNKNOWN; | ||
213 | } | ||
214 | |||
215 | int usbhs_vbus_ctrl(struct usbhs_priv *priv, int enable) | ||
216 | { | ||
217 | struct platform_device *pdev = usbhs_priv_to_pdev(priv); | ||
218 | |||
219 | return usbhs_platform_call(priv, set_vbus, pdev, enable); | ||
220 | } | ||
221 | |||
222 | static void usbhsc_bus_init(struct usbhs_priv *priv) | ||
223 | { | ||
224 | usbhs_write(priv, DVSTCTR, 0); | ||
225 | |||
226 | usbhs_vbus_ctrl(priv, 0); | ||
227 | } | ||
228 | |||
229 | /* | ||
230 | * device configuration | ||
231 | */ | ||
232 | int usbhs_set_device_speed(struct usbhs_priv *priv, int devnum, | ||
233 | u16 upphub, u16 hubport, u16 speed) | ||
234 | { | ||
235 | struct device *dev = usbhs_priv_to_dev(priv); | ||
236 | u16 usbspd = 0; | ||
237 | u32 reg = DEVADD0 + (2 * devnum); | ||
238 | |||
239 | if (devnum > 10) { | ||
240 | dev_err(dev, "cannot set speed to unknown device %d\n", devnum); | ||
241 | return -EIO; | ||
242 | } | ||
243 | |||
244 | if (upphub > 0xA) { | ||
245 | dev_err(dev, "unsupported hub number %d\n", upphub); | ||
246 | return -EIO; | ||
247 | } | ||
248 | |||
249 | switch (speed) { | ||
250 | case USB_SPEED_LOW: | ||
251 | usbspd = USBSPD_SPEED_LOW; | ||
252 | break; | ||
253 | case USB_SPEED_FULL: | ||
254 | usbspd = USBSPD_SPEED_FULL; | ||
255 | break; | ||
256 | case USB_SPEED_HIGH: | ||
257 | usbspd = USBSPD_SPEED_HIGH; | ||
258 | break; | ||
259 | default: | ||
260 | dev_err(dev, "unsupported speed %d\n", speed); | ||
261 | return -EIO; | ||
262 | } | ||
263 | |||
264 | usbhs_write(priv, reg, UPPHUB(upphub) | | ||
265 | HUBPORT(hubport)| | ||
266 | USBSPD(usbspd)); | ||
267 | |||
268 | return 0; | ||
269 | } | ||
270 | |||
271 | /* | ||
150 | * local functions | 272 | * local functions |
151 | */ | 273 | */ |
152 | static void usbhsc_bus_ctrl(struct usbhs_priv *priv, int enable) | 274 | static void usbhsc_set_buswait(struct usbhs_priv *priv) |
153 | { | 275 | { |
154 | int wait = usbhs_get_dparam(priv, buswait_bwait); | 276 | int wait = usbhs_get_dparam(priv, buswait_bwait); |
155 | u16 data = 0; | ||
156 | 277 | ||
157 | if (enable) { | 278 | /* set bus wait if platform have */ |
158 | /* set bus wait if platform have */ | 279 | if (wait) |
159 | if (wait) | 280 | usbhs_bset(priv, BUSWAIT, 0x000F, wait); |
160 | usbhs_bset(priv, BUSWAIT, 0x000F, wait); | ||
161 | } | ||
162 | usbhs_write(priv, DVSTCTR, data); | ||
163 | } | 281 | } |
164 | 282 | ||
165 | /* | 283 | /* |
@@ -191,10 +309,8 @@ static void usbhsc_power_ctrl(struct usbhs_priv *priv, int enable) | |||
191 | 309 | ||
192 | /* USB on */ | 310 | /* USB on */ |
193 | usbhs_sys_clock_ctrl(priv, enable); | 311 | usbhs_sys_clock_ctrl(priv, enable); |
194 | usbhsc_bus_ctrl(priv, enable); | ||
195 | } else { | 312 | } else { |
196 | /* USB off */ | 313 | /* USB off */ |
197 | usbhsc_bus_ctrl(priv, enable); | ||
198 | usbhs_sys_clock_ctrl(priv, enable); | 314 | usbhs_sys_clock_ctrl(priv, enable); |
199 | 315 | ||
200 | /* disable PM */ | 316 | /* disable PM */ |
@@ -203,13 +319,10 @@ static void usbhsc_power_ctrl(struct usbhs_priv *priv, int enable) | |||
203 | } | 319 | } |
204 | 320 | ||
205 | /* | 321 | /* |
206 | * notify hotplug | 322 | * hotplug |
207 | */ | 323 | */ |
208 | static void usbhsc_notify_hotplug(struct work_struct *work) | 324 | static void usbhsc_hotplug(struct usbhs_priv *priv) |
209 | { | 325 | { |
210 | struct usbhs_priv *priv = container_of(work, | ||
211 | struct usbhs_priv, | ||
212 | notify_hotplug_work.work); | ||
213 | struct platform_device *pdev = usbhs_priv_to_pdev(priv); | 326 | struct platform_device *pdev = usbhs_priv_to_pdev(priv); |
214 | struct usbhs_mod *mod = usbhs_mod_get_current(priv); | 327 | struct usbhs_mod *mod = usbhs_mod_get_current(priv); |
215 | int id; | 328 | int id; |
@@ -237,6 +350,10 @@ static void usbhsc_notify_hotplug(struct work_struct *work) | |||
237 | if (usbhsc_flags_has(priv, USBHSF_RUNTIME_PWCTRL)) | 350 | if (usbhsc_flags_has(priv, USBHSF_RUNTIME_PWCTRL)) |
238 | usbhsc_power_ctrl(priv, enable); | 351 | usbhsc_power_ctrl(priv, enable); |
239 | 352 | ||
353 | /* bus init */ | ||
354 | usbhsc_set_buswait(priv); | ||
355 | usbhsc_bus_init(priv); | ||
356 | |||
240 | /* module start */ | 357 | /* module start */ |
241 | usbhs_mod_call(priv, start, priv); | 358 | usbhs_mod_call(priv, start, priv); |
242 | 359 | ||
@@ -246,6 +363,9 @@ static void usbhsc_notify_hotplug(struct work_struct *work) | |||
246 | /* module stop */ | 363 | /* module stop */ |
247 | usbhs_mod_call(priv, stop, priv); | 364 | usbhs_mod_call(priv, stop, priv); |
248 | 365 | ||
366 | /* bus init */ | ||
367 | usbhsc_bus_init(priv); | ||
368 | |||
249 | /* power off */ | 369 | /* power off */ |
250 | if (usbhsc_flags_has(priv, USBHSF_RUNTIME_PWCTRL)) | 370 | if (usbhsc_flags_has(priv, USBHSF_RUNTIME_PWCTRL)) |
251 | usbhsc_power_ctrl(priv, enable); | 371 | usbhsc_power_ctrl(priv, enable); |
@@ -257,6 +377,17 @@ static void usbhsc_notify_hotplug(struct work_struct *work) | |||
257 | } | 377 | } |
258 | } | 378 | } |
259 | 379 | ||
380 | /* | ||
381 | * notify hotplug | ||
382 | */ | ||
383 | static void usbhsc_notify_hotplug(struct work_struct *work) | ||
384 | { | ||
385 | struct usbhs_priv *priv = container_of(work, | ||
386 | struct usbhs_priv, | ||
387 | notify_hotplug_work.work); | ||
388 | usbhsc_hotplug(priv); | ||
389 | } | ||
390 | |||
260 | int usbhsc_drvcllbck_notify_hotplug(struct platform_device *pdev) | 391 | int usbhsc_drvcllbck_notify_hotplug(struct platform_device *pdev) |
261 | { | 392 | { |
262 | struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev); | 393 | struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev); |
@@ -274,7 +405,7 @@ int usbhsc_drvcllbck_notify_hotplug(struct platform_device *pdev) | |||
274 | /* | 405 | /* |
275 | * platform functions | 406 | * platform functions |
276 | */ | 407 | */ |
277 | static int __devinit usbhs_probe(struct platform_device *pdev) | 408 | static int usbhs_probe(struct platform_device *pdev) |
278 | { | 409 | { |
279 | struct renesas_usbhs_platform_info *info = pdev->dev.platform_data; | 410 | struct renesas_usbhs_platform_info *info = pdev->dev.platform_data; |
280 | struct renesas_usbhs_driver_callback *dfunc; | 411 | struct renesas_usbhs_driver_callback *dfunc; |
@@ -315,24 +446,28 @@ static int __devinit usbhs_probe(struct platform_device *pdev) | |||
315 | /* | 446 | /* |
316 | * care platform info | 447 | * care platform info |
317 | */ | 448 | */ |
318 | priv->pfunc = &info->platform_callback; | 449 | memcpy(&priv->pfunc, |
319 | priv->dparam = &info->driver_param; | 450 | &info->platform_callback, |
451 | sizeof(struct renesas_usbhs_platform_callback)); | ||
452 | memcpy(&priv->dparam, | ||
453 | &info->driver_param, | ||
454 | sizeof(struct renesas_usbhs_driver_param)); | ||
320 | 455 | ||
321 | /* set driver callback functions for platform */ | 456 | /* set driver callback functions for platform */ |
322 | dfunc = &info->driver_callback; | 457 | dfunc = &info->driver_callback; |
323 | dfunc->notify_hotplug = usbhsc_drvcllbck_notify_hotplug; | 458 | dfunc->notify_hotplug = usbhsc_drvcllbck_notify_hotplug; |
324 | 459 | ||
325 | /* set default param if platform doesn't have */ | 460 | /* set default param if platform doesn't have */ |
326 | if (!priv->dparam->pipe_type) { | 461 | if (!priv->dparam.pipe_type) { |
327 | priv->dparam->pipe_type = usbhsc_default_pipe_type; | 462 | priv->dparam.pipe_type = usbhsc_default_pipe_type; |
328 | priv->dparam->pipe_size = ARRAY_SIZE(usbhsc_default_pipe_type); | 463 | priv->dparam.pipe_size = ARRAY_SIZE(usbhsc_default_pipe_type); |
329 | } | 464 | } |
330 | if (!priv->dparam->pio_dma_border) | 465 | if (!priv->dparam.pio_dma_border) |
331 | priv->dparam->pio_dma_border = 64; /* 64byte */ | 466 | priv->dparam.pio_dma_border = 64; /* 64byte */ |
332 | 467 | ||
333 | /* FIXME */ | 468 | /* FIXME */ |
334 | /* runtime power control ? */ | 469 | /* runtime power control ? */ |
335 | if (priv->pfunc->get_vbus) | 470 | if (priv->pfunc.get_vbus) |
336 | usbhsc_flags_set(priv, USBHSF_RUNTIME_PWCTRL); | 471 | usbhsc_flags_set(priv, USBHSF_RUNTIME_PWCTRL); |
337 | 472 | ||
338 | /* | 473 | /* |
@@ -443,9 +578,60 @@ static int __devexit usbhs_remove(struct platform_device *pdev) | |||
443 | return 0; | 578 | return 0; |
444 | } | 579 | } |
445 | 580 | ||
581 | static int usbhsc_suspend(struct device *dev) | ||
582 | { | ||
583 | struct usbhs_priv *priv = dev_get_drvdata(dev); | ||
584 | struct usbhs_mod *mod = usbhs_mod_get_current(priv); | ||
585 | |||
586 | if (mod) { | ||
587 | usbhs_mod_call(priv, stop, priv); | ||
588 | usbhs_mod_change(priv, -1); | ||
589 | } | ||
590 | |||
591 | if (mod || !usbhsc_flags_has(priv, USBHSF_RUNTIME_PWCTRL)) | ||
592 | usbhsc_power_ctrl(priv, 0); | ||
593 | |||
594 | return 0; | ||
595 | } | ||
596 | |||
597 | static int usbhsc_resume(struct device *dev) | ||
598 | { | ||
599 | struct usbhs_priv *priv = dev_get_drvdata(dev); | ||
600 | struct platform_device *pdev = usbhs_priv_to_pdev(priv); | ||
601 | |||
602 | usbhs_platform_call(priv, phy_reset, pdev); | ||
603 | |||
604 | if (!usbhsc_flags_has(priv, USBHSF_RUNTIME_PWCTRL)) | ||
605 | usbhsc_power_ctrl(priv, 1); | ||
606 | |||
607 | usbhsc_hotplug(priv); | ||
608 | |||
609 | return 0; | ||
610 | } | ||
611 | |||
612 | static int usbhsc_runtime_nop(struct device *dev) | ||
613 | { | ||
614 | /* Runtime PM callback shared between ->runtime_suspend() | ||
615 | * and ->runtime_resume(). Simply returns success. | ||
616 | * | ||
617 | * This driver re-initializes all registers after | ||
618 | * pm_runtime_get_sync() anyway so there is no need | ||
619 | * to save and restore registers here. | ||
620 | */ | ||
621 | return 0; | ||
622 | } | ||
623 | |||
624 | static const struct dev_pm_ops usbhsc_pm_ops = { | ||
625 | .suspend = usbhsc_suspend, | ||
626 | .resume = usbhsc_resume, | ||
627 | .runtime_suspend = usbhsc_runtime_nop, | ||
628 | .runtime_resume = usbhsc_runtime_nop, | ||
629 | }; | ||
630 | |||
446 | static struct platform_driver renesas_usbhs_driver = { | 631 | static struct platform_driver renesas_usbhs_driver = { |
447 | .driver = { | 632 | .driver = { |
448 | .name = "renesas_usbhs", | 633 | .name = "renesas_usbhs", |
634 | .pm = &usbhsc_pm_ops, | ||
449 | }, | 635 | }, |
450 | .probe = usbhs_probe, | 636 | .probe = usbhs_probe, |
451 | .remove = __devexit_p(usbhs_remove), | 637 | .remove = __devexit_p(usbhs_remove), |
diff --git a/drivers/usb/renesas_usbhs/common.h b/drivers/usb/renesas_usbhs/common.h index b410463a1212..8729da5c3be6 100644 --- a/drivers/usb/renesas_usbhs/common.h +++ b/drivers/usb/renesas_usbhs/common.h | |||
@@ -90,6 +90,17 @@ struct usbhs_priv; | |||
90 | #define PIPE9TRN 0x00BA | 90 | #define PIPE9TRN 0x00BA |
91 | #define PIPEATRE 0x00BC | 91 | #define PIPEATRE 0x00BC |
92 | #define PIPEATRN 0x00BE | 92 | #define PIPEATRN 0x00BE |
93 | #define DEVADD0 0x00D0 /* Device address n configuration */ | ||
94 | #define DEVADD1 0x00D2 | ||
95 | #define DEVADD2 0x00D4 | ||
96 | #define DEVADD3 0x00D6 | ||
97 | #define DEVADD4 0x00D8 | ||
98 | #define DEVADD5 0x00DA | ||
99 | #define DEVADD6 0x00DC | ||
100 | #define DEVADD7 0x00DE | ||
101 | #define DEVADD8 0x00E0 | ||
102 | #define DEVADD9 0x00E2 | ||
103 | #define DEVADDA 0x00E4 | ||
93 | 104 | ||
94 | /* SYSCFG */ | 105 | /* SYSCFG */ |
95 | #define SCKE (1 << 10) /* USB Module Clock Enable */ | 106 | #define SCKE (1 << 10) /* USB Module Clock Enable */ |
@@ -102,6 +113,8 @@ struct usbhs_priv; | |||
102 | /* DVSTCTR */ | 113 | /* DVSTCTR */ |
103 | #define EXTLP (1 << 10) /* Controls the EXTLP pin output state */ | 114 | #define EXTLP (1 << 10) /* Controls the EXTLP pin output state */ |
104 | #define PWEN (1 << 9) /* Controls the PWEN pin output state */ | 115 | #define PWEN (1 << 9) /* Controls the PWEN pin output state */ |
116 | #define USBRST (1 << 6) /* Bus Reset Output */ | ||
117 | #define UACT (1 << 4) /* USB Bus Enable */ | ||
105 | #define RHST (0x7) /* Reset Handshake */ | 118 | #define RHST (0x7) /* Reset Handshake */ |
106 | #define RHST_LOW_SPEED 1 /* Low-speed connection */ | 119 | #define RHST_LOW_SPEED 1 /* Low-speed connection */ |
107 | #define RHST_FULL_SPEED 2 /* Full-speed connection */ | 120 | #define RHST_FULL_SPEED 2 /* Full-speed connection */ |
@@ -159,6 +172,15 @@ struct usbhs_priv; | |||
159 | #define NODATA_STATUS_STAGE 5 /* Control write NoData status stage */ | 172 | #define NODATA_STATUS_STAGE 5 /* Control write NoData status stage */ |
160 | #define SEQUENCE_ERROR 6 /* Control transfer sequence error */ | 173 | #define SEQUENCE_ERROR 6 /* Control transfer sequence error */ |
161 | 174 | ||
175 | /* INTSTS1 */ | ||
176 | #define OVRCR (1 << 15) /* OVRCR Interrupt Status */ | ||
177 | #define BCHG (1 << 14) /* USB Bus Change Interrupt Status */ | ||
178 | #define DTCH (1 << 12) /* USB Disconnection Detect Interrupt Status */ | ||
179 | #define ATTCH (1 << 11) /* ATTCH Interrupt Status */ | ||
180 | #define EOFERR (1 << 6) /* EOF Error Detect Interrupt Status */ | ||
181 | #define SIGN (1 << 5) /* Setup Transaction Error Interrupt Status */ | ||
182 | #define SACK (1 << 4) /* Setup Transaction ACK Response Interrupt Status */ | ||
183 | |||
162 | /* PIPECFG */ | 184 | /* PIPECFG */ |
163 | /* DCPCFG */ | 185 | /* DCPCFG */ |
164 | #define TYPE_NONE (0 << 14) /* Transfer Type */ | 186 | #define TYPE_NONE (0 << 14) /* Transfer Type */ |
@@ -183,9 +205,11 @@ struct usbhs_priv; | |||
183 | /* PIPEnCTR */ | 205 | /* PIPEnCTR */ |
184 | /* DCPCTR */ | 206 | /* DCPCTR */ |
185 | #define BSTS (1 << 15) /* Buffer Status */ | 207 | #define BSTS (1 << 15) /* Buffer Status */ |
208 | #define SUREQ (1 << 14) /* Sending SETUP Token */ | ||
186 | #define CSSTS (1 << 12) /* CSSTS Status */ | 209 | #define CSSTS (1 << 12) /* CSSTS Status */ |
187 | #define SQCLR (1 << 8) /* Toggle Bit Clear */ | ||
188 | #define ACLRM (1 << 9) /* Buffer Auto-Clear Mode */ | 210 | #define ACLRM (1 << 9) /* Buffer Auto-Clear Mode */ |
211 | #define SQCLR (1 << 8) /* Toggle Bit Clear */ | ||
212 | #define SQSET (1 << 7) /* Toggle Bit Set */ | ||
189 | #define PBUSY (1 << 5) /* Pipe Busy */ | 213 | #define PBUSY (1 << 5) /* Pipe Busy */ |
190 | #define PID_MASK (0x3) /* Response PID */ | 214 | #define PID_MASK (0x3) /* Response PID */ |
191 | #define PID_NAK 0 | 215 | #define PID_NAK 0 |
@@ -202,6 +226,14 @@ struct usbhs_priv; | |||
202 | /* FRMNUM */ | 226 | /* FRMNUM */ |
203 | #define FRNM_MASK (0x7FF) | 227 | #define FRNM_MASK (0x7FF) |
204 | 228 | ||
229 | /* DEVADDn */ | ||
230 | #define UPPHUB(x) (((x) & 0xF) << 11) /* HUB Register */ | ||
231 | #define HUBPORT(x) (((x) & 0x7) << 8) /* HUB Port for Target Device */ | ||
232 | #define USBSPD(x) (((x) & 0x3) << 6) /* Device Transfer Rate */ | ||
233 | #define USBSPD_SPEED_LOW 0x1 | ||
234 | #define USBSPD_SPEED_FULL 0x2 | ||
235 | #define USBSPD_SPEED_HIGH 0x3 | ||
236 | |||
205 | /* | 237 | /* |
206 | * struct | 238 | * struct |
207 | */ | 239 | */ |
@@ -210,8 +242,8 @@ struct usbhs_priv { | |||
210 | void __iomem *base; | 242 | void __iomem *base; |
211 | unsigned int irq; | 243 | unsigned int irq; |
212 | 244 | ||
213 | struct renesas_usbhs_platform_callback *pfunc; | 245 | struct renesas_usbhs_platform_callback pfunc; |
214 | struct renesas_usbhs_driver_param *dparam; | 246 | struct renesas_usbhs_driver_param dparam; |
215 | 247 | ||
216 | struct delayed_work notify_hotplug_work; | 248 | struct delayed_work notify_hotplug_work; |
217 | struct platform_device *pdev; | 249 | struct platform_device *pdev; |
@@ -258,15 +290,35 @@ void usbhs_sys_host_ctrl(struct usbhs_priv *priv, int enable); | |||
258 | void usbhs_sys_function_ctrl(struct usbhs_priv *priv, int enable); | 290 | void usbhs_sys_function_ctrl(struct usbhs_priv *priv, int enable); |
259 | 291 | ||
260 | /* | 292 | /* |
293 | * usb request | ||
294 | */ | ||
295 | void usbhs_usbreq_get_val(struct usbhs_priv *priv, struct usb_ctrlrequest *req); | ||
296 | void usbhs_usbreq_set_val(struct usbhs_priv *priv, struct usb_ctrlrequest *req); | ||
297 | |||
298 | /* | ||
299 | * bus | ||
300 | */ | ||
301 | void usbhs_bus_send_sof_enable(struct usbhs_priv *priv); | ||
302 | void usbhs_bus_send_reset(struct usbhs_priv *priv); | ||
303 | int usbhs_bus_get_speed(struct usbhs_priv *priv); | ||
304 | int usbhs_vbus_ctrl(struct usbhs_priv *priv, int enable); | ||
305 | |||
306 | /* | ||
261 | * frame | 307 | * frame |
262 | */ | 308 | */ |
263 | int usbhs_frame_get_num(struct usbhs_priv *priv); | 309 | int usbhs_frame_get_num(struct usbhs_priv *priv); |
264 | 310 | ||
265 | /* | 311 | /* |
312 | * device config | ||
313 | */ | ||
314 | int usbhs_set_device_speed(struct usbhs_priv *priv, int devnum, u16 upphub, | ||
315 | u16 hubport, u16 speed); | ||
316 | |||
317 | /* | ||
266 | * data | 318 | * data |
267 | */ | 319 | */ |
268 | struct usbhs_priv *usbhs_pdev_to_priv(struct platform_device *pdev); | 320 | struct usbhs_priv *usbhs_pdev_to_priv(struct platform_device *pdev); |
269 | #define usbhs_get_dparam(priv, param) (priv->dparam->param) | 321 | #define usbhs_get_dparam(priv, param) (priv->dparam.param) |
270 | #define usbhs_priv_to_pdev(priv) (priv->pdev) | 322 | #define usbhs_priv_to_pdev(priv) (priv->pdev) |
271 | #define usbhs_priv_to_dev(priv) (&priv->pdev->dev) | 323 | #define usbhs_priv_to_dev(priv) (&priv->pdev->dev) |
272 | #define usbhs_priv_to_lock(priv) (&priv->lock) | 324 | #define usbhs_priv_to_lock(priv) (&priv->lock) |
diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index a34430f55fb7..ffdf5d15085e 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c | |||
@@ -54,35 +54,45 @@ static struct usbhs_pkt_handle usbhsf_null_handler = { | |||
54 | }; | 54 | }; |
55 | 55 | ||
56 | void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt, | 56 | void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt, |
57 | struct usbhs_pkt_handle *handler, | 57 | void (*done)(struct usbhs_priv *priv, |
58 | struct usbhs_pkt *pkt), | ||
58 | void *buf, int len, int zero) | 59 | void *buf, int len, int zero) |
59 | { | 60 | { |
60 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | 61 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); |
61 | struct device *dev = usbhs_priv_to_dev(priv); | 62 | struct device *dev = usbhs_priv_to_dev(priv); |
62 | unsigned long flags; | 63 | unsigned long flags; |
63 | 64 | ||
65 | if (!done) { | ||
66 | dev_err(dev, "no done function\n"); | ||
67 | return; | ||
68 | } | ||
69 | |||
64 | /******************** spin lock ********************/ | 70 | /******************** spin lock ********************/ |
65 | usbhs_lock(priv, flags); | 71 | usbhs_lock(priv, flags); |
66 | 72 | ||
67 | if (!handler) { | 73 | if (!pipe->handler) { |
68 | dev_err(dev, "no handler function\n"); | 74 | dev_err(dev, "no handler function\n"); |
69 | handler = &usbhsf_null_handler; | 75 | pipe->handler = &usbhsf_null_handler; |
70 | } | 76 | } |
71 | 77 | ||
72 | list_del_init(&pkt->node); | 78 | list_del_init(&pkt->node); |
73 | list_add_tail(&pkt->node, &pipe->list); | 79 | list_add_tail(&pkt->node, &pipe->list); |
74 | 80 | ||
81 | /* | ||
82 | * each pkt must hold own handler. | ||
83 | * because handler might be changed by its situation. | ||
84 | * dma handler -> pio handler. | ||
85 | */ | ||
75 | pkt->pipe = pipe; | 86 | pkt->pipe = pipe; |
76 | pkt->buf = buf; | 87 | pkt->buf = buf; |
77 | pkt->handler = handler; | 88 | pkt->handler = pipe->handler; |
78 | pkt->length = len; | 89 | pkt->length = len; |
79 | pkt->zero = zero; | 90 | pkt->zero = zero; |
80 | pkt->actual = 0; | 91 | pkt->actual = 0; |
92 | pkt->done = done; | ||
81 | 93 | ||
82 | usbhs_unlock(priv, flags); | 94 | usbhs_unlock(priv, flags); |
83 | /******************** spin unlock ******************/ | 95 | /******************** spin unlock ******************/ |
84 | |||
85 | usbhs_pkt_start(pipe); | ||
86 | } | 96 | } |
87 | 97 | ||
88 | static void __usbhsf_pkt_del(struct usbhs_pkt *pkt) | 98 | static void __usbhsf_pkt_del(struct usbhs_pkt *pkt) |
@@ -118,10 +128,15 @@ struct usbhs_pkt *usbhs_pkt_pop(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt) | |||
118 | return pkt; | 128 | return pkt; |
119 | } | 129 | } |
120 | 130 | ||
121 | int __usbhs_pkt_handler(struct usbhs_pipe *pipe, int type) | 131 | enum { |
132 | USBHSF_PKT_PREPARE, | ||
133 | USBHSF_PKT_TRY_RUN, | ||
134 | USBHSF_PKT_DMA_DONE, | ||
135 | }; | ||
136 | |||
137 | static int usbhsf_pkt_handler(struct usbhs_pipe *pipe, int type) | ||
122 | { | 138 | { |
123 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | 139 | 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; | 140 | struct usbhs_pkt *pkt; |
126 | struct device *dev = usbhs_priv_to_dev(priv); | 141 | struct device *dev = usbhs_priv_to_dev(priv); |
127 | int (*func)(struct usbhs_pkt *pkt, int *is_done); | 142 | int (*func)(struct usbhs_pkt *pkt, int *is_done); |
@@ -161,13 +176,18 @@ __usbhs_pkt_handler_end: | |||
161 | /******************** spin unlock ******************/ | 176 | /******************** spin unlock ******************/ |
162 | 177 | ||
163 | if (is_done) { | 178 | if (is_done) { |
164 | info->done(pkt); | 179 | pkt->done(priv, pkt); |
165 | usbhs_pkt_start(pipe); | 180 | usbhs_pkt_start(pipe); |
166 | } | 181 | } |
167 | 182 | ||
168 | return ret; | 183 | return ret; |
169 | } | 184 | } |
170 | 185 | ||
186 | void usbhs_pkt_start(struct usbhs_pipe *pipe) | ||
187 | { | ||
188 | usbhsf_pkt_handler(pipe, USBHSF_PKT_PREPARE); | ||
189 | } | ||
190 | |||
171 | /* | 191 | /* |
172 | * irq enable/disable function | 192 | * irq enable/disable function |
173 | */ | 193 | */ |
@@ -276,9 +296,13 @@ static int usbhsf_fifo_select(struct usbhs_pipe *pipe, | |||
276 | usbhsf_fifo_is_busy(fifo)) | 296 | usbhsf_fifo_is_busy(fifo)) |
277 | return -EBUSY; | 297 | return -EBUSY; |
278 | 298 | ||
279 | if (usbhs_pipe_is_dcp(pipe)) | 299 | if (usbhs_pipe_is_dcp(pipe)) { |
280 | base |= (1 == write) << 5; /* ISEL */ | 300 | base |= (1 == write) << 5; /* ISEL */ |
281 | 301 | ||
302 | if (usbhs_mod_is_host(priv)) | ||
303 | usbhs_dcp_dir_for_host(pipe, write); | ||
304 | } | ||
305 | |||
282 | /* "base" will be used below */ | 306 | /* "base" will be used below */ |
283 | usbhs_write(priv, fifo->sel, base | MBW_32); | 307 | usbhs_write(priv, fifo->sel, base | MBW_32); |
284 | 308 | ||
@@ -297,6 +321,151 @@ static int usbhsf_fifo_select(struct usbhs_pipe *pipe, | |||
297 | } | 321 | } |
298 | 322 | ||
299 | /* | 323 | /* |
324 | * DCP status stage | ||
325 | */ | ||
326 | static int usbhs_dcp_dir_switch_to_write(struct usbhs_pkt *pkt, int *is_done) | ||
327 | { | ||
328 | struct usbhs_pipe *pipe = pkt->pipe; | ||
329 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | ||
330 | struct usbhs_fifo *fifo = usbhsf_get_cfifo(priv); /* CFIFO */ | ||
331 | struct device *dev = usbhs_priv_to_dev(priv); | ||
332 | int ret; | ||
333 | |||
334 | usbhs_pipe_disable(pipe); | ||
335 | |||
336 | ret = usbhsf_fifo_select(pipe, fifo, 1); | ||
337 | if (ret < 0) { | ||
338 | dev_err(dev, "%s() faile\n", __func__); | ||
339 | return ret; | ||
340 | } | ||
341 | |||
342 | usbhs_pipe_sequence_data1(pipe); /* DATA1 */ | ||
343 | |||
344 | usbhsf_fifo_clear(pipe, fifo); | ||
345 | usbhsf_send_terminator(pipe, fifo); | ||
346 | |||
347 | usbhsf_fifo_unselect(pipe, fifo); | ||
348 | |||
349 | usbhsf_tx_irq_ctrl(pipe, 1); | ||
350 | usbhs_pipe_enable(pipe); | ||
351 | |||
352 | return ret; | ||
353 | } | ||
354 | |||
355 | static int usbhs_dcp_dir_switch_to_read(struct usbhs_pkt *pkt, int *is_done) | ||
356 | { | ||
357 | struct usbhs_pipe *pipe = pkt->pipe; | ||
358 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | ||
359 | struct usbhs_fifo *fifo = usbhsf_get_cfifo(priv); /* CFIFO */ | ||
360 | struct device *dev = usbhs_priv_to_dev(priv); | ||
361 | int ret; | ||
362 | |||
363 | usbhs_pipe_disable(pipe); | ||
364 | |||
365 | ret = usbhsf_fifo_select(pipe, fifo, 0); | ||
366 | if (ret < 0) { | ||
367 | dev_err(dev, "%s() fail\n", __func__); | ||
368 | return ret; | ||
369 | } | ||
370 | |||
371 | usbhs_pipe_sequence_data1(pipe); /* DATA1 */ | ||
372 | usbhsf_fifo_clear(pipe, fifo); | ||
373 | |||
374 | usbhsf_fifo_unselect(pipe, fifo); | ||
375 | |||
376 | usbhsf_rx_irq_ctrl(pipe, 1); | ||
377 | usbhs_pipe_enable(pipe); | ||
378 | |||
379 | return ret; | ||
380 | |||
381 | } | ||
382 | |||
383 | static int usbhs_dcp_dir_switch_done(struct usbhs_pkt *pkt, int *is_done) | ||
384 | { | ||
385 | struct usbhs_pipe *pipe = pkt->pipe; | ||
386 | |||
387 | if (pkt->handler == &usbhs_dcp_status_stage_in_handler) | ||
388 | usbhsf_tx_irq_ctrl(pipe, 0); | ||
389 | else | ||
390 | usbhsf_rx_irq_ctrl(pipe, 0); | ||
391 | |||
392 | pkt->actual = pkt->length; | ||
393 | *is_done = 1; | ||
394 | |||
395 | return 0; | ||
396 | } | ||
397 | |||
398 | struct usbhs_pkt_handle usbhs_dcp_status_stage_in_handler = { | ||
399 | .prepare = usbhs_dcp_dir_switch_to_write, | ||
400 | .try_run = usbhs_dcp_dir_switch_done, | ||
401 | }; | ||
402 | |||
403 | struct usbhs_pkt_handle usbhs_dcp_status_stage_out_handler = { | ||
404 | .prepare = usbhs_dcp_dir_switch_to_read, | ||
405 | .try_run = usbhs_dcp_dir_switch_done, | ||
406 | }; | ||
407 | |||
408 | /* | ||
409 | * DCP data stage (push) | ||
410 | */ | ||
411 | static int usbhsf_dcp_data_stage_try_push(struct usbhs_pkt *pkt, int *is_done) | ||
412 | { | ||
413 | struct usbhs_pipe *pipe = pkt->pipe; | ||
414 | |||
415 | usbhs_pipe_sequence_data1(pipe); /* DATA1 */ | ||
416 | |||
417 | /* | ||
418 | * change handler to PIO push | ||
419 | */ | ||
420 | pkt->handler = &usbhs_fifo_pio_push_handler; | ||
421 | |||
422 | return pkt->handler->prepare(pkt, is_done); | ||
423 | } | ||
424 | |||
425 | struct usbhs_pkt_handle usbhs_dcp_data_stage_out_handler = { | ||
426 | .prepare = usbhsf_dcp_data_stage_try_push, | ||
427 | }; | ||
428 | |||
429 | /* | ||
430 | * DCP data stage (pop) | ||
431 | */ | ||
432 | static int usbhsf_dcp_data_stage_prepare_pop(struct usbhs_pkt *pkt, | ||
433 | int *is_done) | ||
434 | { | ||
435 | struct usbhs_pipe *pipe = pkt->pipe; | ||
436 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | ||
437 | struct usbhs_fifo *fifo = usbhsf_get_cfifo(priv); | ||
438 | |||
439 | if (usbhs_pipe_is_busy(pipe)) | ||
440 | return 0; | ||
441 | |||
442 | /* | ||
443 | * prepare pop for DCP should | ||
444 | * - change DCP direction, | ||
445 | * - clear fifo | ||
446 | * - DATA1 | ||
447 | */ | ||
448 | usbhs_pipe_disable(pipe); | ||
449 | |||
450 | usbhs_pipe_sequence_data1(pipe); /* DATA1 */ | ||
451 | |||
452 | usbhsf_fifo_select(pipe, fifo, 0); | ||
453 | usbhsf_fifo_clear(pipe, fifo); | ||
454 | usbhsf_fifo_unselect(pipe, fifo); | ||
455 | |||
456 | /* | ||
457 | * change handler to PIO pop | ||
458 | */ | ||
459 | pkt->handler = &usbhs_fifo_pio_pop_handler; | ||
460 | |||
461 | return pkt->handler->prepare(pkt, is_done); | ||
462 | } | ||
463 | |||
464 | struct usbhs_pkt_handle usbhs_dcp_data_stage_in_handler = { | ||
465 | .prepare = usbhsf_dcp_data_stage_prepare_pop, | ||
466 | }; | ||
467 | |||
468 | /* | ||
300 | * PIO push handler | 469 | * PIO push handler |
301 | */ | 470 | */ |
302 | static int usbhsf_pio_try_push(struct usbhs_pkt *pkt, int *is_done) | 471 | static int usbhsf_pio_try_push(struct usbhs_pkt *pkt, int *is_done) |
@@ -452,6 +621,20 @@ static int usbhsf_pio_try_pop(struct usbhs_pkt *pkt, int *is_done) | |||
452 | total_len = len; | 621 | total_len = len; |
453 | 622 | ||
454 | /* | 623 | /* |
624 | * update actual length first here to decide disable pipe. | ||
625 | * if this pipe keeps BUF status and all data were popped, | ||
626 | * then, next interrupt/token will be issued again | ||
627 | */ | ||
628 | pkt->actual += total_len; | ||
629 | |||
630 | if ((pkt->actual == pkt->length) || /* receive all data */ | ||
631 | (total_len < maxp)) { /* short packet */ | ||
632 | *is_done = 1; | ||
633 | usbhsf_rx_irq_ctrl(pipe, 0); | ||
634 | usbhs_pipe_disable(pipe); /* disable pipe first */ | ||
635 | } | ||
636 | |||
637 | /* | ||
455 | * Buffer clear if Zero-Length packet | 638 | * Buffer clear if Zero-Length packet |
456 | * | 639 | * |
457 | * see | 640 | * see |
@@ -481,16 +664,7 @@ static int usbhsf_pio_try_pop(struct usbhs_pkt *pkt, int *is_done) | |||
481 | buf[i] = (data >> ((i & 0x03) * 8)) & 0xff; | 664 | buf[i] = (data >> ((i & 0x03) * 8)) & 0xff; |
482 | } | 665 | } |
483 | 666 | ||
484 | pkt->actual += total_len; | ||
485 | |||
486 | usbhs_fifo_read_end: | 667 | 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", | 668 | dev_dbg(dev, " recv %d (%d/ %d/ %d/ %d)\n", |
495 | usbhs_pipe_number(pipe), | 669 | usbhs_pipe_number(pipe), |
496 | pkt->length, pkt->actual, *is_done, pkt->zero); | 670 | pkt->length, pkt->actual, *is_done, pkt->zero); |
@@ -646,7 +820,7 @@ static int usbhsf_dma_prepare_push(struct usbhs_pkt *pkt, int *is_done) | |||
646 | if (len % 4) /* 32bit alignment */ | 820 | if (len % 4) /* 32bit alignment */ |
647 | goto usbhsf_pio_prepare_push; | 821 | goto usbhsf_pio_prepare_push; |
648 | 822 | ||
649 | if (((u32)pkt->buf + pkt->actual) & 0x7) /* 8byte alignment */ | 823 | if ((uintptr_t)(pkt->buf + pkt->actual) & 0x7) /* 8byte alignment */ |
650 | goto usbhsf_pio_prepare_push; | 824 | goto usbhsf_pio_prepare_push; |
651 | 825 | ||
652 | /* get enable DMA fifo */ | 826 | /* get enable DMA fifo */ |
@@ -723,7 +897,7 @@ static int usbhsf_dma_try_pop(struct usbhs_pkt *pkt, int *is_done) | |||
723 | if (!fifo) | 897 | if (!fifo) |
724 | goto usbhsf_pio_prepare_pop; | 898 | goto usbhsf_pio_prepare_pop; |
725 | 899 | ||
726 | if (((u32)pkt->buf + pkt->actual) & 0x7) /* 8byte alignment */ | 900 | if ((uintptr_t)(pkt->buf + pkt->actual) & 0x7) /* 8byte alignment */ |
727 | goto usbhsf_pio_prepare_pop; | 901 | goto usbhsf_pio_prepare_pop; |
728 | 902 | ||
729 | ret = usbhsf_fifo_select(pipe, fifo, 0); | 903 | ret = usbhsf_fifo_select(pipe, fifo, 0); |
@@ -884,7 +1058,7 @@ static int usbhsf_irq_empty(struct usbhs_priv *priv, | |||
884 | if (!(irq_state->bempsts & (1 << i))) | 1058 | if (!(irq_state->bempsts & (1 << i))) |
885 | continue; | 1059 | continue; |
886 | 1060 | ||
887 | ret = usbhs_pkt_run(pipe); | 1061 | ret = usbhsf_pkt_handler(pipe, USBHSF_PKT_TRY_RUN); |
888 | if (ret < 0) | 1062 | if (ret < 0) |
889 | dev_err(dev, "irq_empty run_error %d : %d\n", i, ret); | 1063 | dev_err(dev, "irq_empty run_error %d : %d\n", i, ret); |
890 | } | 1064 | } |
@@ -914,7 +1088,7 @@ static int usbhsf_irq_ready(struct usbhs_priv *priv, | |||
914 | if (!(irq_state->brdysts & (1 << i))) | 1088 | if (!(irq_state->brdysts & (1 << i))) |
915 | continue; | 1089 | continue; |
916 | 1090 | ||
917 | ret = usbhs_pkt_run(pipe); | 1091 | ret = usbhsf_pkt_handler(pipe, USBHSF_PKT_TRY_RUN); |
918 | if (ret < 0) | 1092 | if (ret < 0) |
919 | dev_err(dev, "irq_ready run_error %d : %d\n", i, ret); | 1093 | dev_err(dev, "irq_ready run_error %d : %d\n", i, ret); |
920 | } | 1094 | } |
@@ -929,7 +1103,7 @@ static void usbhsf_dma_complete(void *arg) | |||
929 | struct device *dev = usbhs_priv_to_dev(priv); | 1103 | struct device *dev = usbhs_priv_to_dev(priv); |
930 | int ret; | 1104 | int ret; |
931 | 1105 | ||
932 | ret = usbhs_pkt_dmadone(pipe); | 1106 | ret = usbhsf_pkt_handler(pipe, USBHSF_PKT_DMA_DONE); |
933 | if (ret < 0) | 1107 | if (ret < 0) |
934 | dev_err(dev, "dma_complete run_error %d : %d\n", | 1108 | dev_err(dev, "dma_complete run_error %d : %d\n", |
935 | usbhs_pipe_number(pipe), ret); | 1109 | usbhs_pipe_number(pipe), ret); |
diff --git a/drivers/usb/renesas_usbhs/fifo.h b/drivers/usb/renesas_usbhs/fifo.h index ed6d8e56c13c..32a7b246b28d 100644 --- a/drivers/usb/renesas_usbhs/fifo.h +++ b/drivers/usb/renesas_usbhs/fifo.h | |||
@@ -51,6 +51,8 @@ struct usbhs_pkt { | |||
51 | struct list_head node; | 51 | struct list_head node; |
52 | struct usbhs_pipe *pipe; | 52 | struct usbhs_pipe *pipe; |
53 | struct usbhs_pkt_handle *handler; | 53 | struct usbhs_pkt_handle *handler; |
54 | void (*done)(struct usbhs_priv *priv, | ||
55 | struct usbhs_pkt *pkt); | ||
54 | dma_addr_t dma; | 56 | dma_addr_t dma; |
55 | void *buf; | 57 | void *buf; |
56 | int length; | 58 | int length; |
@@ -76,12 +78,6 @@ void usbhs_fifo_quit(struct usbhs_priv *priv); | |||
76 | /* | 78 | /* |
77 | * packet info | 79 | * packet info |
78 | */ | 80 | */ |
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; | 81 | extern struct usbhs_pkt_handle usbhs_fifo_pio_push_handler; |
86 | extern struct usbhs_pkt_handle usbhs_fifo_pio_pop_handler; | 82 | extern struct usbhs_pkt_handle usbhs_fifo_pio_pop_handler; |
87 | extern struct usbhs_pkt_handle usbhs_ctrl_stage_end_handler; | 83 | extern struct usbhs_pkt_handle usbhs_ctrl_stage_end_handler; |
@@ -89,16 +85,18 @@ extern struct usbhs_pkt_handle usbhs_ctrl_stage_end_handler; | |||
89 | extern struct usbhs_pkt_handle usbhs_fifo_dma_push_handler; | 85 | extern struct usbhs_pkt_handle usbhs_fifo_dma_push_handler; |
90 | extern struct usbhs_pkt_handle usbhs_fifo_dma_pop_handler; | 86 | extern struct usbhs_pkt_handle usbhs_fifo_dma_pop_handler; |
91 | 87 | ||
88 | extern struct usbhs_pkt_handle usbhs_dcp_status_stage_in_handler; | ||
89 | extern struct usbhs_pkt_handle usbhs_dcp_status_stage_out_handler; | ||
90 | |||
91 | extern struct usbhs_pkt_handle usbhs_dcp_data_stage_in_handler; | ||
92 | extern struct usbhs_pkt_handle usbhs_dcp_data_stage_out_handler; | ||
92 | 93 | ||
93 | void usbhs_pkt_init(struct usbhs_pkt *pkt); | 94 | void usbhs_pkt_init(struct usbhs_pkt *pkt); |
94 | void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt, | 95 | void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt, |
95 | struct usbhs_pkt_handle *handler, | 96 | void (*done)(struct usbhs_priv *priv, |
97 | struct usbhs_pkt *pkt), | ||
96 | void *buf, int len, int zero); | 98 | void *buf, int len, int zero); |
97 | struct usbhs_pkt *usbhs_pkt_pop(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt); | 99 | struct usbhs_pkt *usbhs_pkt_pop(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt); |
98 | int __usbhs_pkt_handler(struct usbhs_pipe *pipe, int type); | 100 | void usbhs_pkt_start(struct usbhs_pipe *pipe); |
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 | 101 | ||
104 | #endif /* RENESAS_USB_FIFO_H */ | 102 | #endif /* RENESAS_USB_FIFO_H */ |
diff --git a/drivers/usb/renesas_usbhs/mod.c b/drivers/usb/renesas_usbhs/mod.c index a577f8f4064c..053f86d70009 100644 --- a/drivers/usb/renesas_usbhs/mod.c +++ b/drivers/usb/renesas_usbhs/mod.c | |||
@@ -58,7 +58,7 @@ void usbhs_mod_autonomy_mode(struct usbhs_priv *priv) | |||
58 | struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv); | 58 | struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv); |
59 | 59 | ||
60 | info->irq_vbus = usbhsm_autonomy_irq_vbus; | 60 | info->irq_vbus = usbhsm_autonomy_irq_vbus; |
61 | priv->pfunc->get_vbus = usbhsm_autonomy_get_vbus; | 61 | priv->pfunc.get_vbus = usbhsm_autonomy_get_vbus; |
62 | 62 | ||
63 | usbhs_irq_callback_update(priv, NULL); | 63 | usbhs_irq_callback_update(priv, NULL); |
64 | } | 64 | } |
@@ -93,8 +93,9 @@ struct usbhs_mod *usbhs_mod_get(struct usbhs_priv *priv, int id) | |||
93 | return ret; | 93 | return ret; |
94 | } | 94 | } |
95 | 95 | ||
96 | int usbhs_mod_is_host(struct usbhs_priv *priv, struct usbhs_mod *mod) | 96 | int usbhs_mod_is_host(struct usbhs_priv *priv) |
97 | { | 97 | { |
98 | struct usbhs_mod *mod = usbhs_mod_get_current(priv); | ||
98 | struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv); | 99 | struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv); |
99 | 100 | ||
100 | if (!mod) | 101 | if (!mod) |
@@ -139,13 +140,17 @@ int usbhs_mod_probe(struct usbhs_priv *priv) | |||
139 | /* | 140 | /* |
140 | * install host/gadget driver | 141 | * install host/gadget driver |
141 | */ | 142 | */ |
142 | ret = usbhs_mod_gadget_probe(priv); | 143 | ret = usbhs_mod_host_probe(priv); |
143 | if (ret < 0) | 144 | if (ret < 0) |
144 | return ret; | 145 | return ret; |
145 | 146 | ||
147 | ret = usbhs_mod_gadget_probe(priv); | ||
148 | if (ret < 0) | ||
149 | goto mod_init_host_err; | ||
150 | |||
146 | /* irq settings */ | 151 | /* irq settings */ |
147 | ret = request_irq(priv->irq, usbhs_interrupt, | 152 | ret = request_irq(priv->irq, usbhs_interrupt, |
148 | IRQF_DISABLED, dev_name(dev), priv); | 153 | 0, dev_name(dev), priv); |
149 | if (ret) { | 154 | if (ret) { |
150 | dev_err(dev, "irq request err\n"); | 155 | dev_err(dev, "irq request err\n"); |
151 | goto mod_init_gadget_err; | 156 | goto mod_init_gadget_err; |
@@ -155,12 +160,15 @@ int usbhs_mod_probe(struct usbhs_priv *priv) | |||
155 | 160 | ||
156 | mod_init_gadget_err: | 161 | mod_init_gadget_err: |
157 | usbhs_mod_gadget_remove(priv); | 162 | usbhs_mod_gadget_remove(priv); |
163 | mod_init_host_err: | ||
164 | usbhs_mod_host_remove(priv); | ||
158 | 165 | ||
159 | return ret; | 166 | return ret; |
160 | } | 167 | } |
161 | 168 | ||
162 | void usbhs_mod_remove(struct usbhs_priv *priv) | 169 | void usbhs_mod_remove(struct usbhs_priv *priv) |
163 | { | 170 | { |
171 | usbhs_mod_host_remove(priv); | ||
164 | usbhs_mod_gadget_remove(priv); | 172 | usbhs_mod_gadget_remove(priv); |
165 | free_irq(priv->irq, priv); | 173 | free_irq(priv->irq, priv); |
166 | } | 174 | } |
@@ -168,20 +176,6 @@ void usbhs_mod_remove(struct usbhs_priv *priv) | |||
168 | /* | 176 | /* |
169 | * status functions | 177 | * status functions |
170 | */ | 178 | */ |
171 | int usbhs_status_get_usb_speed(struct usbhs_irq_state *irq_state) | ||
172 | { | ||
173 | switch (irq_state->dvstctr & RHST) { | ||
174 | case RHST_LOW_SPEED: | ||
175 | return USB_SPEED_LOW; | ||
176 | case RHST_FULL_SPEED: | ||
177 | return USB_SPEED_FULL; | ||
178 | case RHST_HIGH_SPEED: | ||
179 | return USB_SPEED_HIGH; | ||
180 | } | ||
181 | |||
182 | return USB_SPEED_UNKNOWN; | ||
183 | } | ||
184 | |||
185 | int usbhs_status_get_device_state(struct usbhs_irq_state *irq_state) | 179 | int usbhs_status_get_device_state(struct usbhs_irq_state *irq_state) |
186 | { | 180 | { |
187 | int state = irq_state->intsts0 & DVSQ_MASK; | 181 | int state = irq_state->intsts0 & DVSQ_MASK; |
@@ -221,8 +215,6 @@ static void usbhs_status_get_each_irq(struct usbhs_priv *priv, | |||
221 | state->intsts0 = usbhs_read(priv, INTSTS0); | 215 | state->intsts0 = usbhs_read(priv, INTSTS0); |
222 | state->intsts1 = usbhs_read(priv, INTSTS1); | 216 | state->intsts1 = usbhs_read(priv, INTSTS1); |
223 | 217 | ||
224 | state->dvstctr = usbhs_read(priv, DVSTCTR); | ||
225 | |||
226 | /* mask */ | 218 | /* mask */ |
227 | if (mod) { | 219 | if (mod) { |
228 | state->brdysts = usbhs_read(priv, BRDYSTS); | 220 | state->brdysts = usbhs_read(priv, BRDYSTS); |
@@ -269,6 +261,8 @@ static irqreturn_t usbhs_interrupt(int irq, void *data) | |||
269 | * see also | 261 | * see also |
270 | * usbhs_irq_setting_update | 262 | * usbhs_irq_setting_update |
271 | */ | 263 | */ |
264 | |||
265 | /* INTSTS0 */ | ||
272 | if (irq_state.intsts0 & VBINT) | 266 | if (irq_state.intsts0 & VBINT) |
273 | usbhs_mod_info_call(priv, irq_vbus, priv, &irq_state); | 267 | usbhs_mod_info_call(priv, irq_vbus, priv, &irq_state); |
274 | 268 | ||
@@ -284,15 +278,38 @@ static irqreturn_t usbhs_interrupt(int irq, void *data) | |||
284 | if (irq_state.intsts0 & BRDY) | 278 | if (irq_state.intsts0 & BRDY) |
285 | usbhs_mod_call(priv, irq_ready, priv, &irq_state); | 279 | usbhs_mod_call(priv, irq_ready, priv, &irq_state); |
286 | 280 | ||
281 | /* INTSTS1 */ | ||
282 | if (irq_state.intsts1 & ATTCH) | ||
283 | usbhs_mod_call(priv, irq_attch, priv, &irq_state); | ||
284 | |||
285 | if (irq_state.intsts1 & DTCH) | ||
286 | usbhs_mod_call(priv, irq_dtch, priv, &irq_state); | ||
287 | |||
288 | if (irq_state.intsts1 & SIGN) | ||
289 | usbhs_mod_call(priv, irq_sign, priv, &irq_state); | ||
290 | |||
291 | if (irq_state.intsts1 & SACK) | ||
292 | usbhs_mod_call(priv, irq_sack, priv, &irq_state); | ||
293 | |||
287 | return IRQ_HANDLED; | 294 | return IRQ_HANDLED; |
288 | } | 295 | } |
289 | 296 | ||
290 | void usbhs_irq_callback_update(struct usbhs_priv *priv, struct usbhs_mod *mod) | 297 | void usbhs_irq_callback_update(struct usbhs_priv *priv, struct usbhs_mod *mod) |
291 | { | 298 | { |
292 | u16 intenb0 = 0; | 299 | u16 intenb0 = 0; |
300 | u16 intenb1 = 0; | ||
293 | struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv); | 301 | struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv); |
294 | 302 | ||
303 | /* | ||
304 | * BEMPENB/BRDYENB are picky. | ||
305 | * below method is required | ||
306 | * | ||
307 | * - clear INTSTS0 | ||
308 | * - update BEMPENB/BRDYENB | ||
309 | * - update INTSTS0 | ||
310 | */ | ||
295 | usbhs_write(priv, INTENB0, 0); | 311 | usbhs_write(priv, INTENB0, 0); |
312 | usbhs_write(priv, INTENB1, 0); | ||
296 | 313 | ||
297 | usbhs_write(priv, BEMPENB, 0); | 314 | usbhs_write(priv, BEMPENB, 0); |
298 | usbhs_write(priv, BRDYENB, 0); | 315 | usbhs_write(priv, BRDYENB, 0); |
@@ -310,6 +327,9 @@ void usbhs_irq_callback_update(struct usbhs_priv *priv, struct usbhs_mod *mod) | |||
310 | intenb0 |= VBSE; | 327 | intenb0 |= VBSE; |
311 | 328 | ||
312 | if (mod) { | 329 | if (mod) { |
330 | /* | ||
331 | * INTSTS0 | ||
332 | */ | ||
313 | if (mod->irq_ctrl_stage) | 333 | if (mod->irq_ctrl_stage) |
314 | intenb0 |= CTRE; | 334 | intenb0 |= CTRE; |
315 | 335 | ||
@@ -322,7 +342,26 @@ void usbhs_irq_callback_update(struct usbhs_priv *priv, struct usbhs_mod *mod) | |||
322 | usbhs_write(priv, BRDYENB, mod->irq_brdysts); | 342 | usbhs_write(priv, BRDYENB, mod->irq_brdysts); |
323 | intenb0 |= BRDYE; | 343 | intenb0 |= BRDYE; |
324 | } | 344 | } |
345 | |||
346 | /* | ||
347 | * INTSTS1 | ||
348 | */ | ||
349 | if (mod->irq_attch) | ||
350 | intenb1 |= ATTCHE; | ||
351 | |||
352 | if (mod->irq_attch) | ||
353 | intenb1 |= DTCHE; | ||
354 | |||
355 | if (mod->irq_sign) | ||
356 | intenb1 |= SIGNE; | ||
357 | |||
358 | if (mod->irq_sack) | ||
359 | intenb1 |= SACKE; | ||
325 | } | 360 | } |
326 | 361 | ||
327 | usbhs_write(priv, INTENB0, intenb0); | 362 | if (intenb0) |
363 | usbhs_write(priv, INTENB0, intenb0); | ||
364 | |||
365 | if (intenb1) | ||
366 | usbhs_write(priv, INTENB1, intenb1); | ||
328 | } | 367 | } |
diff --git a/drivers/usb/renesas_usbhs/mod.h b/drivers/usb/renesas_usbhs/mod.h index 5c845a28a21c..6c6875533f01 100644 --- a/drivers/usb/renesas_usbhs/mod.h +++ b/drivers/usb/renesas_usbhs/mod.h | |||
@@ -30,7 +30,6 @@ struct usbhs_irq_state { | |||
30 | u16 brdysts; | 30 | u16 brdysts; |
31 | u16 nrdysts; | 31 | u16 nrdysts; |
32 | u16 bempsts; | 32 | u16 bempsts; |
33 | u16 dvstctr; | ||
34 | }; | 33 | }; |
35 | 34 | ||
36 | struct usbhs_mod { | 35 | struct usbhs_mod { |
@@ -42,26 +41,48 @@ struct usbhs_mod { | |||
42 | int (*start)(struct usbhs_priv *priv); | 41 | int (*start)(struct usbhs_priv *priv); |
43 | int (*stop)(struct usbhs_priv *priv); | 42 | int (*stop)(struct usbhs_priv *priv); |
44 | 43 | ||
45 | /* INTSTS0 :: DVST (DVSQ) */ | 44 | /* |
45 | * INTSTS0 | ||
46 | */ | ||
47 | |||
48 | /* DVST (DVSQ) */ | ||
46 | int (*irq_dev_state)(struct usbhs_priv *priv, | 49 | int (*irq_dev_state)(struct usbhs_priv *priv, |
47 | struct usbhs_irq_state *irq_state); | 50 | struct usbhs_irq_state *irq_state); |
48 | 51 | ||
49 | /* INTSTS0 :: CTRT (CTSQ) */ | 52 | /* CTRT (CTSQ) */ |
50 | int (*irq_ctrl_stage)(struct usbhs_priv *priv, | 53 | int (*irq_ctrl_stage)(struct usbhs_priv *priv, |
51 | struct usbhs_irq_state *irq_state); | 54 | struct usbhs_irq_state *irq_state); |
52 | 55 | ||
53 | /* INTSTS0 :: BEMP */ | 56 | /* BEMP / BEMPSTS */ |
54 | /* BEMPSTS */ | ||
55 | int (*irq_empty)(struct usbhs_priv *priv, | 57 | int (*irq_empty)(struct usbhs_priv *priv, |
56 | struct usbhs_irq_state *irq_state); | 58 | struct usbhs_irq_state *irq_state); |
57 | u16 irq_bempsts; | 59 | u16 irq_bempsts; |
58 | 60 | ||
59 | /* INTSTS0 :: BRDY */ | 61 | /* BRDY / BRDYSTS */ |
60 | /* BRDYSTS */ | ||
61 | int (*irq_ready)(struct usbhs_priv *priv, | 62 | int (*irq_ready)(struct usbhs_priv *priv, |
62 | struct usbhs_irq_state *irq_state); | 63 | struct usbhs_irq_state *irq_state); |
63 | u16 irq_brdysts; | 64 | u16 irq_brdysts; |
64 | 65 | ||
66 | /* | ||
67 | * INTSTS1 | ||
68 | */ | ||
69 | |||
70 | /* ATTCHE */ | ||
71 | int (*irq_attch)(struct usbhs_priv *priv, | ||
72 | struct usbhs_irq_state *irq_state); | ||
73 | |||
74 | /* DTCHE */ | ||
75 | int (*irq_dtch)(struct usbhs_priv *priv, | ||
76 | struct usbhs_irq_state *irq_state); | ||
77 | |||
78 | /* SIGN */ | ||
79 | int (*irq_sign)(struct usbhs_priv *priv, | ||
80 | struct usbhs_irq_state *irq_state); | ||
81 | |||
82 | /* SACK */ | ||
83 | int (*irq_sack)(struct usbhs_priv *priv, | ||
84 | struct usbhs_irq_state *irq_state); | ||
85 | |||
65 | struct usbhs_priv *priv; | 86 | struct usbhs_priv *priv; |
66 | }; | 87 | }; |
67 | 88 | ||
@@ -89,7 +110,7 @@ struct usbhs_mod_info { | |||
89 | struct usbhs_mod *usbhs_mod_get(struct usbhs_priv *priv, int id); | 110 | struct usbhs_mod *usbhs_mod_get(struct usbhs_priv *priv, int id); |
90 | struct usbhs_mod *usbhs_mod_get_current(struct usbhs_priv *priv); | 111 | struct usbhs_mod *usbhs_mod_get_current(struct usbhs_priv *priv); |
91 | void usbhs_mod_register(struct usbhs_priv *priv, struct usbhs_mod *usb, int id); | 112 | void usbhs_mod_register(struct usbhs_priv *priv, struct usbhs_mod *usb, int id); |
92 | int usbhs_mod_is_host(struct usbhs_priv *priv, struct usbhs_mod *mod); | 113 | int usbhs_mod_is_host(struct usbhs_priv *priv); |
93 | int usbhs_mod_change(struct usbhs_priv *priv, int id); | 114 | int usbhs_mod_change(struct usbhs_priv *priv, int id); |
94 | int usbhs_mod_probe(struct usbhs_priv *priv); | 115 | int usbhs_mod_probe(struct usbhs_priv *priv); |
95 | void usbhs_mod_remove(struct usbhs_priv *priv); | 116 | void usbhs_mod_remove(struct usbhs_priv *priv); |
@@ -99,7 +120,6 @@ void usbhs_mod_autonomy_mode(struct usbhs_priv *priv); | |||
99 | /* | 120 | /* |
100 | * status functions | 121 | * status functions |
101 | */ | 122 | */ |
102 | int usbhs_status_get_usb_speed(struct usbhs_irq_state *irq_state); | ||
103 | int usbhs_status_get_device_state(struct usbhs_irq_state *irq_state); | 123 | int usbhs_status_get_device_state(struct usbhs_irq_state *irq_state); |
104 | int usbhs_status_get_ctrl_stage(struct usbhs_irq_state *irq_state); | 124 | int usbhs_status_get_ctrl_stage(struct usbhs_irq_state *irq_state); |
105 | 125 | ||
@@ -119,11 +139,26 @@ void usbhs_irq_callback_update(struct usbhs_priv *priv, struct usbhs_mod *mod); | |||
119 | }) | 139 | }) |
120 | 140 | ||
121 | /* | 141 | /* |
122 | * gadget control | 142 | * host / gadget control |
123 | */ | 143 | */ |
124 | #ifdef CONFIG_USB_RENESAS_USBHS_UDC | 144 | #if defined(CONFIG_USB_RENESAS_USBHS_HCD) || \ |
125 | extern int __devinit usbhs_mod_gadget_probe(struct usbhs_priv *priv); | 145 | defined(CONFIG_USB_RENESAS_USBHS_HCD_MODULE) |
126 | extern void __devexit usbhs_mod_gadget_remove(struct usbhs_priv *priv); | 146 | extern int usbhs_mod_host_probe(struct usbhs_priv *priv); |
147 | extern int usbhs_mod_host_remove(struct usbhs_priv *priv); | ||
148 | #else | ||
149 | static inline int usbhs_mod_host_probe(struct usbhs_priv *priv) | ||
150 | { | ||
151 | return 0; | ||
152 | } | ||
153 | static inline void usbhs_mod_host_remove(struct usbhs_priv *priv) | ||
154 | { | ||
155 | } | ||
156 | #endif | ||
157 | |||
158 | #if defined(CONFIG_USB_RENESAS_USBHS_UDC) || \ | ||
159 | defined(CONFIG_USB_RENESAS_USBHS_UDC_MODULE) | ||
160 | extern int usbhs_mod_gadget_probe(struct usbhs_priv *priv); | ||
161 | extern void usbhs_mod_gadget_remove(struct usbhs_priv *priv); | ||
127 | #else | 162 | #else |
128 | static inline int usbhs_mod_gadget_probe(struct usbhs_priv *priv) | 163 | static inline int usbhs_mod_gadget_probe(struct usbhs_priv *priv) |
129 | { | 164 | { |
diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c index cb2d451d511e..d9717e0bc1ff 100644 --- a/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/drivers/usb/renesas_usbhs/mod_gadget.c | |||
@@ -39,7 +39,6 @@ struct usbhsg_uep { | |||
39 | char ep_name[EP_NAME_SIZE]; | 39 | char ep_name[EP_NAME_SIZE]; |
40 | 40 | ||
41 | struct usbhsg_gpriv *gpriv; | 41 | struct usbhsg_gpriv *gpriv; |
42 | struct usbhs_pkt_handle *handler; | ||
43 | }; | 42 | }; |
44 | 43 | ||
45 | struct usbhsg_gpriv { | 44 | struct usbhsg_gpriv { |
@@ -128,25 +127,6 @@ LIST_HEAD(the_controller_link); | |||
128 | /* | 127 | /* |
129 | * queue push/pop | 128 | * queue push/pop |
130 | */ | 129 | */ |
131 | static void usbhsg_queue_push(struct usbhsg_uep *uep, | ||
132 | struct usbhsg_request *ureq) | ||
133 | { | ||
134 | struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); | ||
135 | struct device *dev = usbhsg_gpriv_to_dev(gpriv); | ||
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; | ||
139 | |||
140 | req->actual = 0; | ||
141 | req->status = -EINPROGRESS; | ||
142 | usbhs_pkt_push(pipe, pkt, uep->handler, | ||
143 | req->buf, req->length, req->zero); | ||
144 | |||
145 | dev_dbg(dev, "pipe %d : queue push (%d)\n", | ||
146 | usbhs_pipe_number(pipe), | ||
147 | req->length); | ||
148 | } | ||
149 | |||
150 | static void usbhsg_queue_pop(struct usbhsg_uep *uep, | 130 | static void usbhsg_queue_pop(struct usbhsg_uep *uep, |
151 | struct usbhsg_request *ureq, | 131 | struct usbhsg_request *ureq, |
152 | int status) | 132 | int status) |
@@ -161,7 +141,7 @@ static void usbhsg_queue_pop(struct usbhsg_uep *uep, | |||
161 | ureq->req.complete(&uep->ep, &ureq->req); | 141 | ureq->req.complete(&uep->ep, &ureq->req); |
162 | } | 142 | } |
163 | 143 | ||
164 | static void usbhsg_queue_done(struct usbhs_pkt *pkt) | 144 | static void usbhsg_queue_done(struct usbhs_priv *priv, struct usbhs_pkt *pkt) |
165 | { | 145 | { |
166 | struct usbhs_pipe *pipe = pkt->pipe; | 146 | struct usbhs_pipe *pipe = pkt->pipe; |
167 | struct usbhsg_uep *uep = usbhsg_pipe_to_uep(pipe); | 147 | struct usbhsg_uep *uep = usbhsg_pipe_to_uep(pipe); |
@@ -172,6 +152,26 @@ static void usbhsg_queue_done(struct usbhs_pkt *pkt) | |||
172 | usbhsg_queue_pop(uep, ureq, 0); | 152 | usbhsg_queue_pop(uep, ureq, 0); |
173 | } | 153 | } |
174 | 154 | ||
155 | static void usbhsg_queue_push(struct usbhsg_uep *uep, | ||
156 | struct usbhsg_request *ureq) | ||
157 | { | ||
158 | struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); | ||
159 | struct device *dev = usbhsg_gpriv_to_dev(gpriv); | ||
160 | struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); | ||
161 | struct usbhs_pkt *pkt = usbhsg_ureq_to_pkt(ureq); | ||
162 | struct usb_request *req = &ureq->req; | ||
163 | |||
164 | req->actual = 0; | ||
165 | req->status = -EINPROGRESS; | ||
166 | usbhs_pkt_push(pipe, pkt, usbhsg_queue_done, | ||
167 | req->buf, req->length, req->zero); | ||
168 | usbhs_pkt_start(pipe); | ||
169 | |||
170 | dev_dbg(dev, "pipe %d : queue push (%d)\n", | ||
171 | usbhs_pipe_number(pipe), | ||
172 | req->length); | ||
173 | } | ||
174 | |||
175 | /* | 175 | /* |
176 | * dma map/unmap | 176 | * dma map/unmap |
177 | */ | 177 | */ |
@@ -265,7 +265,7 @@ static int usbhsg_recip_handler_std_clear_endpoint(struct usbhs_priv *priv, | |||
265 | 265 | ||
266 | if (!usbhsg_status_has(gpriv, USBHSG_STATUS_WEDGE)) { | 266 | if (!usbhsg_status_has(gpriv, USBHSG_STATUS_WEDGE)) { |
267 | usbhs_pipe_disable(pipe); | 267 | usbhs_pipe_disable(pipe); |
268 | usbhs_pipe_clear_sequence(pipe); | 268 | usbhs_pipe_sequence_data0(pipe); |
269 | usbhs_pipe_enable(pipe); | 269 | usbhs_pipe_enable(pipe); |
270 | } | 270 | } |
271 | 271 | ||
@@ -355,7 +355,7 @@ static int usbhsg_irq_dev_state(struct usbhs_priv *priv, | |||
355 | struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); | 355 | struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); |
356 | struct device *dev = usbhsg_gpriv_to_dev(gpriv); | 356 | struct device *dev = usbhsg_gpriv_to_dev(gpriv); |
357 | 357 | ||
358 | gpriv->gadget.speed = usbhs_status_get_usb_speed(irq_state); | 358 | gpriv->gadget.speed = usbhs_bus_get_speed(priv); |
359 | 359 | ||
360 | dev_dbg(dev, "state = %x : speed : %d\n", | 360 | dev_dbg(dev, "state = %x : speed : %d\n", |
361 | usbhs_status_get_device_state(irq_state), | 361 | usbhs_status_get_device_state(irq_state), |
@@ -389,13 +389,13 @@ static int usbhsg_irq_ctrl_stage(struct usbhs_priv *priv, | |||
389 | 389 | ||
390 | switch (stage) { | 390 | switch (stage) { |
391 | case READ_DATA_STAGE: | 391 | case READ_DATA_STAGE: |
392 | dcp->handler = &usbhs_fifo_pio_push_handler; | 392 | pipe->handler = &usbhs_fifo_pio_push_handler; |
393 | break; | 393 | break; |
394 | case WRITE_DATA_STAGE: | 394 | case WRITE_DATA_STAGE: |
395 | dcp->handler = &usbhs_fifo_pio_pop_handler; | 395 | pipe->handler = &usbhs_fifo_pio_pop_handler; |
396 | break; | 396 | break; |
397 | case NODATA_STATUS_STAGE: | 397 | case NODATA_STATUS_STAGE: |
398 | dcp->handler = &usbhs_ctrl_stage_end_handler; | 398 | pipe->handler = &usbhs_ctrl_stage_end_handler; |
399 | break; | 399 | break; |
400 | default: | 400 | default: |
401 | return ret; | 401 | return ret; |
@@ -479,24 +479,31 @@ static int usbhsg_ep_enable(struct usb_ep *ep, | |||
479 | */ | 479 | */ |
480 | if (uep->pipe) { | 480 | if (uep->pipe) { |
481 | usbhs_pipe_clear(uep->pipe); | 481 | usbhs_pipe_clear(uep->pipe); |
482 | usbhs_pipe_clear_sequence(uep->pipe); | 482 | usbhs_pipe_sequence_data0(uep->pipe); |
483 | return 0; | 483 | return 0; |
484 | } | 484 | } |
485 | 485 | ||
486 | pipe = usbhs_pipe_malloc(priv, desc); | 486 | pipe = usbhs_pipe_malloc(priv, |
487 | usb_endpoint_type(desc), | ||
488 | usb_endpoint_dir_in(desc)); | ||
487 | if (pipe) { | 489 | if (pipe) { |
488 | uep->pipe = pipe; | 490 | uep->pipe = pipe; |
489 | pipe->mod_private = uep; | 491 | pipe->mod_private = uep; |
490 | 492 | ||
493 | /* set epnum / maxp */ | ||
494 | usbhs_pipe_config_update(pipe, 0, | ||
495 | usb_endpoint_num(desc), | ||
496 | usb_endpoint_maxp(desc)); | ||
497 | |||
491 | /* | 498 | /* |
492 | * usbhs_fifo_dma_push/pop_handler try to | 499 | * usbhs_fifo_dma_push/pop_handler try to |
493 | * use dmaengine if possible. | 500 | * use dmaengine if possible. |
494 | * It will use pio handler if impossible. | 501 | * It will use pio handler if impossible. |
495 | */ | 502 | */ |
496 | if (usb_endpoint_dir_in(desc)) | 503 | if (usb_endpoint_dir_in(desc)) |
497 | uep->handler = &usbhs_fifo_dma_push_handler; | 504 | pipe->handler = &usbhs_fifo_dma_push_handler; |
498 | else | 505 | else |
499 | uep->handler = &usbhs_fifo_dma_pop_handler; | 506 | pipe->handler = &usbhs_fifo_dma_pop_handler; |
500 | 507 | ||
501 | ret = 0; | 508 | ret = 0; |
502 | } | 509 | } |
@@ -659,7 +666,6 @@ static int usbhsg_try_start(struct usbhs_priv *priv, u32 status) | |||
659 | * pipe initialize and enable DCP | 666 | * pipe initialize and enable DCP |
660 | */ | 667 | */ |
661 | usbhs_pipe_init(priv, | 668 | usbhs_pipe_init(priv, |
662 | usbhsg_queue_done, | ||
663 | usbhsg_dma_map_ctrl); | 669 | usbhsg_dma_map_ctrl); |
664 | usbhs_fifo_init(priv); | 670 | usbhs_fifo_init(priv); |
665 | usbhsg_uep_init(gpriv); | 671 | usbhsg_uep_init(gpriv); |
@@ -667,6 +673,7 @@ static int usbhsg_try_start(struct usbhs_priv *priv, u32 status) | |||
667 | /* dcp init */ | 673 | /* dcp init */ |
668 | dcp->pipe = usbhs_dcp_malloc(priv); | 674 | dcp->pipe = usbhs_dcp_malloc(priv); |
669 | dcp->pipe->mod_private = dcp; | 675 | dcp->pipe->mod_private = dcp; |
676 | usbhs_pipe_config_update(dcp->pipe, 0, 0, 64); | ||
670 | 677 | ||
671 | /* | 678 | /* |
672 | * system config enble | 679 | * system config enble |
@@ -730,10 +737,6 @@ static int usbhsg_try_stop(struct usbhs_priv *priv, u32 status) | |||
730 | 737 | ||
731 | usbhsg_pipe_disable(dcp); | 738 | usbhsg_pipe_disable(dcp); |
732 | 739 | ||
733 | if (gpriv->driver && | ||
734 | gpriv->driver->disconnect) | ||
735 | gpriv->driver->disconnect(&gpriv->gadget); | ||
736 | |||
737 | dev_dbg(dev, "stop gadget\n"); | 740 | dev_dbg(dev, "stop gadget\n"); |
738 | 741 | ||
739 | return 0; | 742 | return 0; |
@@ -744,31 +747,19 @@ static int usbhsg_try_stop(struct usbhs_priv *priv, u32 status) | |||
744 | * linux usb function | 747 | * linux usb function |
745 | * | 748 | * |
746 | */ | 749 | */ |
747 | static int usbhsg_gadget_start(struct usb_gadget_driver *driver, | 750 | static int usbhsg_gadget_start(struct usb_gadget *gadget, |
748 | int (*bind)(struct usb_gadget *)) | 751 | struct usb_gadget_driver *driver) |
749 | { | 752 | { |
750 | struct usbhsg_gpriv *gpriv; | 753 | struct usbhsg_gpriv *gpriv = usbhsg_gadget_to_gpriv(gadget); |
751 | struct usbhs_priv *priv; | 754 | struct usbhs_priv *priv; |
752 | struct device *dev; | 755 | struct device *dev; |
753 | int ret; | 756 | int ret; |
754 | 757 | ||
755 | if (!bind || | 758 | if (!driver || |
756 | !driver || | ||
757 | !driver->setup || | 759 | !driver->setup || |
758 | driver->speed != USB_SPEED_HIGH) | 760 | driver->speed != USB_SPEED_HIGH) |
759 | return -EINVAL; | 761 | return -EINVAL; |
760 | 762 | ||
761 | /* | ||
762 | * find unused controller | ||
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: | ||
771 | |||
772 | dev = usbhsg_gpriv_to_dev(gpriv); | 763 | dev = usbhsg_gpriv_to_dev(gpriv); |
773 | priv = usbhsg_gpriv_to_priv(gpriv); | 764 | priv = usbhsg_gpriv_to_priv(gpriv); |
774 | 765 | ||
@@ -782,19 +773,8 @@ find_unused_controller: | |||
782 | goto add_fail; | 773 | goto add_fail; |
783 | } | 774 | } |
784 | 775 | ||
785 | ret = bind(&gpriv->gadget); | ||
786 | if (ret) { | ||
787 | dev_err(dev, "bind to driver %s error %d\n", | ||
788 | driver->driver.name, ret); | ||
789 | goto bind_fail; | ||
790 | } | ||
791 | |||
792 | dev_dbg(dev, "bind %s\n", driver->driver.name); | ||
793 | |||
794 | return usbhsg_try_start(priv, USBHSG_STATUS_REGISTERD); | 776 | return usbhsg_try_start(priv, USBHSG_STATUS_REGISTERD); |
795 | 777 | ||
796 | bind_fail: | ||
797 | device_del(&gpriv->gadget.dev); | ||
798 | add_fail: | 778 | add_fail: |
799 | gpriv->driver = NULL; | 779 | gpriv->driver = NULL; |
800 | gpriv->gadget.dev.driver = NULL; | 780 | gpriv->gadget.dev.driver = NULL; |
@@ -802,9 +782,10 @@ add_fail: | |||
802 | return ret; | 782 | return ret; |
803 | } | 783 | } |
804 | 784 | ||
805 | static int usbhsg_gadget_stop(struct usb_gadget_driver *driver) | 785 | static int usbhsg_gadget_stop(struct usb_gadget *gadget, |
786 | struct usb_gadget_driver *driver) | ||
806 | { | 787 | { |
807 | struct usbhsg_gpriv *gpriv; | 788 | struct usbhsg_gpriv *gpriv = usbhsg_gadget_to_gpriv(gadget); |
808 | struct usbhs_priv *priv; | 789 | struct usbhs_priv *priv; |
809 | struct device *dev; | 790 | struct device *dev; |
810 | 791 | ||
@@ -812,17 +793,6 @@ static int usbhsg_gadget_stop(struct usb_gadget_driver *driver) | |||
812 | !driver->unbind) | 793 | !driver->unbind) |
813 | return -EINVAL; | 794 | return -EINVAL; |
814 | 795 | ||
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 | |||
826 | dev = usbhsg_gpriv_to_dev(gpriv); | 796 | dev = usbhsg_gpriv_to_dev(gpriv); |
827 | priv = usbhsg_gpriv_to_priv(gpriv); | 797 | priv = usbhsg_gpriv_to_priv(gpriv); |
828 | 798 | ||
@@ -830,12 +800,6 @@ find_matching_controller: | |||
830 | device_del(&gpriv->gadget.dev); | 800 | device_del(&gpriv->gadget.dev); |
831 | gpriv->driver = NULL; | 801 | gpriv->driver = NULL; |
832 | 802 | ||
833 | if (driver->disconnect) | ||
834 | driver->disconnect(&gpriv->gadget); | ||
835 | |||
836 | driver->unbind(&gpriv->gadget); | ||
837 | dev_dbg(dev, "unbind %s\n", driver->driver.name); | ||
838 | |||
839 | return 0; | 803 | return 0; |
840 | } | 804 | } |
841 | 805 | ||
@@ -852,8 +816,8 @@ static int usbhsg_get_frame(struct usb_gadget *gadget) | |||
852 | 816 | ||
853 | static struct usb_gadget_ops usbhsg_gadget_ops = { | 817 | static struct usb_gadget_ops usbhsg_gadget_ops = { |
854 | .get_frame = usbhsg_get_frame, | 818 | .get_frame = usbhsg_get_frame, |
855 | .start = usbhsg_gadget_start, | 819 | .udc_start = usbhsg_gadget_start, |
856 | .stop = usbhsg_gadget_stop, | 820 | .udc_stop = usbhsg_gadget_stop, |
857 | }; | 821 | }; |
858 | 822 | ||
859 | static int usbhsg_start(struct usbhs_priv *priv) | 823 | static int usbhsg_start(struct usbhs_priv *priv) |
@@ -866,7 +830,7 @@ static int usbhsg_stop(struct usbhs_priv *priv) | |||
866 | return usbhsg_try_stop(priv, USBHSG_STATUS_STARTED); | 830 | return usbhsg_try_stop(priv, USBHSG_STATUS_STARTED); |
867 | } | 831 | } |
868 | 832 | ||
869 | int __devinit usbhs_mod_gadget_probe(struct usbhs_priv *priv) | 833 | int usbhs_mod_gadget_probe(struct usbhs_priv *priv) |
870 | { | 834 | { |
871 | struct usbhsg_gpriv *gpriv; | 835 | struct usbhsg_gpriv *gpriv; |
872 | struct usbhsg_uep *uep; | 836 | struct usbhsg_uep *uep; |
@@ -963,7 +927,7 @@ usbhs_mod_gadget_probe_err_gpriv: | |||
963 | return ret; | 927 | return ret; |
964 | } | 928 | } |
965 | 929 | ||
966 | void __devexit usbhs_mod_gadget_remove(struct usbhs_priv *priv) | 930 | void usbhs_mod_gadget_remove(struct usbhs_priv *priv) |
967 | { | 931 | { |
968 | struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); | 932 | struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); |
969 | 933 | ||
diff --git a/drivers/usb/renesas_usbhs/mod_host.c b/drivers/usb/renesas_usbhs/mod_host.c new file mode 100644 index 000000000000..bade761a1e52 --- /dev/null +++ b/drivers/usb/renesas_usbhs/mod_host.c | |||
@@ -0,0 +1,1327 @@ | |||
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/io.h> | ||
18 | #include <linux/list.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/slab.h> | ||
22 | #include <linux/usb.h> | ||
23 | #include <linux/usb/hcd.h> | ||
24 | #include "common.h" | ||
25 | |||
26 | /* | ||
27 | *** HARDWARE LIMITATION *** | ||
28 | * | ||
29 | * 1) renesas_usbhs has a limited number of controllable devices. | ||
30 | * it can control only 9 devices in generally. | ||
31 | * see DEVADDn / DCPMAXP / PIPEMAXP. | ||
32 | * | ||
33 | * 2) renesas_usbhs pipe number is limited. | ||
34 | * the pipe will be re-used for each devices. | ||
35 | * so, software should control DATA0/1 sequence of each devices. | ||
36 | */ | ||
37 | |||
38 | |||
39 | /* | ||
40 | * image of mod_host | ||
41 | * | ||
42 | * +--------+ | ||
43 | * | udev 0 | --> it is used when set address | ||
44 | * +--------+ | ||
45 | * | ||
46 | * +--------+ pipes are reused for each uep. | ||
47 | * | udev 1 |-+- [uep 0 (dcp) ] --+ pipe will be switched when | ||
48 | * +--------+ | | target device was changed | ||
49 | * +- [uep 1 (bulk)] --|---+ +--------------+ | ||
50 | * | +--------------> | pipe0 (dcp) | | ||
51 | * +- [uep 2 (bulk)] --|---|---+ +--------------+ | ||
52 | * | | | | pipe1 (isoc) | | ||
53 | * +--------+ | | | +--------------+ | ||
54 | * | udev 2 |-+- [uep 0 (dcp) ] --+ +-- |------> | pipe2 (bulk) | | ||
55 | * +--------+ | | | | +--------------+ | ||
56 | * +- [uep 1 (int) ] --|-+ | +------> | pipe3 (bulk) | | ||
57 | * | | | | +--------------+ | ||
58 | * +--------+ | +-|---|------> | pipe4 (int) | | ||
59 | * | udev 3 |-+- [uep 0 (dcp) ] --+ | | +--------------+ | ||
60 | * +--------+ | | | | .... | | ||
61 | * +- [uep 1 (bulk)] ------+ | | .... | | ||
62 | * | | | ||
63 | * +- [uep 2 (bulk)]-----------+ | ||
64 | */ | ||
65 | |||
66 | |||
67 | /* | ||
68 | * struct | ||
69 | */ | ||
70 | struct usbhsh_pipe_info { | ||
71 | unsigned int usr_cnt; /* see usbhsh_endpoint_alloc() */ | ||
72 | }; | ||
73 | |||
74 | struct usbhsh_request { | ||
75 | struct urb *urb; | ||
76 | struct usbhs_pkt pkt; | ||
77 | struct list_head ureq_link; /* see hpriv :: ureq_link_xxx */ | ||
78 | }; | ||
79 | |||
80 | struct usbhsh_device { | ||
81 | struct usb_device *usbv; | ||
82 | struct list_head ep_list_head; /* list of usbhsh_ep */ | ||
83 | }; | ||
84 | |||
85 | struct usbhsh_ep { | ||
86 | struct usbhs_pipe *pipe; | ||
87 | struct usbhsh_device *udev; /* attached udev */ | ||
88 | struct list_head ep_list; /* list to usbhsh_device */ | ||
89 | |||
90 | int maxp; | ||
91 | }; | ||
92 | |||
93 | #define USBHSH_DEVICE_MAX 10 /* see DEVADDn / DCPMAXP / PIPEMAXP */ | ||
94 | #define USBHSH_PORT_MAX 7 /* see DEVADDn :: HUBPORT */ | ||
95 | struct usbhsh_hpriv { | ||
96 | struct usbhs_mod mod; | ||
97 | struct usbhs_pipe *dcp; | ||
98 | |||
99 | struct usbhsh_device udev[USBHSH_DEVICE_MAX]; | ||
100 | |||
101 | struct usbhsh_pipe_info *pipe_info; | ||
102 | int pipe_size; | ||
103 | |||
104 | u32 port_stat; /* USB_PORT_STAT_xxx */ | ||
105 | |||
106 | struct completion setup_ack_done; | ||
107 | |||
108 | /* see usbhsh_req_alloc/free */ | ||
109 | struct list_head ureq_link_active; | ||
110 | struct list_head ureq_link_free; | ||
111 | }; | ||
112 | |||
113 | |||
114 | static const char usbhsh_hcd_name[] = "renesas_usbhs host"; | ||
115 | |||
116 | /* | ||
117 | * macro | ||
118 | */ | ||
119 | #define usbhsh_priv_to_hpriv(priv) \ | ||
120 | container_of(usbhs_mod_get(priv, USBHS_HOST), struct usbhsh_hpriv, mod) | ||
121 | |||
122 | #define __usbhsh_for_each_hpipe(start, pos, h, i) \ | ||
123 | for (i = start, pos = (h)->hpipe + i; \ | ||
124 | i < (h)->hpipe_size; \ | ||
125 | i++, pos = (h)->hpipe + i) | ||
126 | |||
127 | #define usbhsh_for_each_hpipe(pos, hpriv, i) \ | ||
128 | __usbhsh_for_each_hpipe(1, pos, hpriv, i) | ||
129 | |||
130 | #define usbhsh_for_each_hpipe_with_dcp(pos, hpriv, i) \ | ||
131 | __usbhsh_for_each_hpipe(0, pos, hpriv, i) | ||
132 | |||
133 | #define __usbhsh_for_each_udev(start, pos, h, i) \ | ||
134 | for (i = start, pos = (h)->udev + i; \ | ||
135 | i < USBHSH_DEVICE_MAX; \ | ||
136 | i++, pos = (h)->udev + i) | ||
137 | |||
138 | #define usbhsh_for_each_udev(pos, hpriv, i) \ | ||
139 | __usbhsh_for_each_udev(1, pos, hpriv, i) | ||
140 | |||
141 | #define usbhsh_for_each_udev_with_dev0(pos, hpriv, i) \ | ||
142 | __usbhsh_for_each_udev(0, pos, hpriv, i) | ||
143 | |||
144 | #define usbhsh_hcd_to_hpriv(h) (struct usbhsh_hpriv *)((h)->hcd_priv) | ||
145 | #define usbhsh_hcd_to_dev(h) ((h)->self.controller) | ||
146 | |||
147 | #define usbhsh_hpriv_to_priv(h) ((h)->mod.priv) | ||
148 | #define usbhsh_hpriv_to_dcp(h) ((h)->dcp) | ||
149 | #define usbhsh_hpriv_to_hcd(h) \ | ||
150 | container_of((void *)h, struct usb_hcd, hcd_priv) | ||
151 | |||
152 | #define usbhsh_ep_to_uep(u) ((u)->hcpriv) | ||
153 | #define usbhsh_uep_to_pipe(u) ((u)->pipe) | ||
154 | #define usbhsh_uep_to_udev(u) ((u)->udev) | ||
155 | #define usbhsh_urb_to_ureq(u) ((u)->hcpriv) | ||
156 | #define usbhsh_urb_to_usbv(u) ((u)->dev) | ||
157 | |||
158 | #define usbhsh_usbv_to_udev(d) dev_get_drvdata(&(d)->dev) | ||
159 | |||
160 | #define usbhsh_udev_to_usbv(h) ((h)->usbv) | ||
161 | |||
162 | #define usbhsh_pipe_info(p) ((p)->mod_private) | ||
163 | |||
164 | #define usbhsh_device_number(h, d) ((int)((d) - (h)->udev)) | ||
165 | #define usbhsh_device_nth(h, d) ((h)->udev + d) | ||
166 | #define usbhsh_device0(h) usbhsh_device_nth(h, 0) | ||
167 | |||
168 | #define usbhsh_port_stat_init(h) ((h)->port_stat = 0) | ||
169 | #define usbhsh_port_stat_set(h, s) ((h)->port_stat |= (s)) | ||
170 | #define usbhsh_port_stat_clear(h, s) ((h)->port_stat &= ~(s)) | ||
171 | #define usbhsh_port_stat_get(h) ((h)->port_stat) | ||
172 | |||
173 | #define usbhsh_pkt_to_req(p) \ | ||
174 | container_of((void *)p, struct usbhsh_request, pkt) | ||
175 | |||
176 | /* | ||
177 | * req alloc/free | ||
178 | */ | ||
179 | static void usbhsh_req_list_init(struct usbhsh_hpriv *hpriv) | ||
180 | { | ||
181 | INIT_LIST_HEAD(&hpriv->ureq_link_active); | ||
182 | INIT_LIST_HEAD(&hpriv->ureq_link_free); | ||
183 | } | ||
184 | |||
185 | static void usbhsh_req_list_quit(struct usbhsh_hpriv *hpriv) | ||
186 | { | ||
187 | struct usb_hcd *hcd = usbhsh_hpriv_to_hcd(hpriv); | ||
188 | struct device *dev = usbhsh_hcd_to_dev(hcd); | ||
189 | struct usbhsh_request *ureq, *next; | ||
190 | |||
191 | /* kfree all active ureq */ | ||
192 | list_for_each_entry_safe(ureq, next, | ||
193 | &hpriv->ureq_link_active, | ||
194 | ureq_link) { | ||
195 | dev_err(dev, "active ureq (%p) is force freed\n", ureq); | ||
196 | kfree(ureq); | ||
197 | } | ||
198 | |||
199 | /* kfree all free ureq */ | ||
200 | list_for_each_entry_safe(ureq, next, &hpriv->ureq_link_free, ureq_link) | ||
201 | kfree(ureq); | ||
202 | } | ||
203 | |||
204 | static struct usbhsh_request *usbhsh_req_alloc(struct usbhsh_hpriv *hpriv, | ||
205 | struct urb *urb, | ||
206 | gfp_t mem_flags) | ||
207 | { | ||
208 | struct usbhsh_request *ureq; | ||
209 | struct usbhs_priv *priv = usbhsh_hpriv_to_priv(hpriv); | ||
210 | struct device *dev = usbhs_priv_to_dev(priv); | ||
211 | |||
212 | if (list_empty(&hpriv->ureq_link_free)) { | ||
213 | /* | ||
214 | * create new one if there is no free ureq | ||
215 | */ | ||
216 | ureq = kzalloc(sizeof(struct usbhsh_request), mem_flags); | ||
217 | if (ureq) | ||
218 | INIT_LIST_HEAD(&ureq->ureq_link); | ||
219 | } else { | ||
220 | /* | ||
221 | * reuse "free" ureq if exist | ||
222 | */ | ||
223 | ureq = list_entry(hpriv->ureq_link_free.next, | ||
224 | struct usbhsh_request, | ||
225 | ureq_link); | ||
226 | if (ureq) | ||
227 | list_del_init(&ureq->ureq_link); | ||
228 | } | ||
229 | |||
230 | if (!ureq) { | ||
231 | dev_err(dev, "ureq alloc fail\n"); | ||
232 | return NULL; | ||
233 | } | ||
234 | |||
235 | usbhs_pkt_init(&ureq->pkt); | ||
236 | |||
237 | /* | ||
238 | * push it to "active" list | ||
239 | */ | ||
240 | list_add_tail(&ureq->ureq_link, &hpriv->ureq_link_active); | ||
241 | ureq->urb = urb; | ||
242 | |||
243 | return ureq; | ||
244 | } | ||
245 | |||
246 | static void usbhsh_req_free(struct usbhsh_hpriv *hpriv, | ||
247 | struct usbhsh_request *ureq) | ||
248 | { | ||
249 | struct usbhs_pkt *pkt = &ureq->pkt; | ||
250 | |||
251 | usbhs_pkt_init(pkt); | ||
252 | |||
253 | /* | ||
254 | * removed from "active" list, | ||
255 | * and push it to "free" list | ||
256 | */ | ||
257 | ureq->urb = NULL; | ||
258 | list_del_init(&ureq->ureq_link); | ||
259 | list_add_tail(&ureq->ureq_link, &hpriv->ureq_link_free); | ||
260 | } | ||
261 | |||
262 | /* | ||
263 | * device control | ||
264 | */ | ||
265 | |||
266 | static int usbhsh_device_has_endpoint(struct usbhsh_device *udev) | ||
267 | { | ||
268 | return !list_empty(&udev->ep_list_head); | ||
269 | } | ||
270 | |||
271 | static struct usbhsh_device *usbhsh_device_alloc(struct usbhsh_hpriv *hpriv, | ||
272 | struct urb *urb) | ||
273 | { | ||
274 | struct usbhsh_device *udev = NULL; | ||
275 | struct usb_hcd *hcd = usbhsh_hpriv_to_hcd(hpriv); | ||
276 | struct device *dev = usbhsh_hcd_to_dev(hcd); | ||
277 | struct usb_device *usbv = usbhsh_urb_to_usbv(urb); | ||
278 | struct usbhs_priv *priv = usbhsh_hpriv_to_priv(hpriv); | ||
279 | int i; | ||
280 | |||
281 | /* | ||
282 | * device 0 | ||
283 | */ | ||
284 | if (0 == usb_pipedevice(urb->pipe)) { | ||
285 | udev = usbhsh_device0(hpriv); | ||
286 | goto usbhsh_device_find; | ||
287 | } | ||
288 | |||
289 | /* | ||
290 | * find unused device | ||
291 | */ | ||
292 | usbhsh_for_each_udev(udev, hpriv, i) { | ||
293 | if (usbhsh_udev_to_usbv(udev)) | ||
294 | continue; | ||
295 | goto usbhsh_device_find; | ||
296 | } | ||
297 | |||
298 | dev_err(dev, "no free usbhsh_device\n"); | ||
299 | |||
300 | return NULL; | ||
301 | |||
302 | usbhsh_device_find: | ||
303 | if (usbhsh_device_has_endpoint(udev)) | ||
304 | dev_warn(dev, "udev have old endpoint\n"); | ||
305 | |||
306 | /* uep will be attached */ | ||
307 | INIT_LIST_HEAD(&udev->ep_list_head); | ||
308 | |||
309 | /* | ||
310 | * usbhsh_usbv_to_udev() | ||
311 | * usbhsh_udev_to_usbv() | ||
312 | * will be enable | ||
313 | */ | ||
314 | dev_set_drvdata(&usbv->dev, udev); | ||
315 | udev->usbv = usbv; | ||
316 | |||
317 | /* set device config */ | ||
318 | usbhs_set_device_speed(priv, | ||
319 | usbhsh_device_number(hpriv, udev), | ||
320 | usbhsh_device_number(hpriv, udev), | ||
321 | 0, /* FIXME no parent */ | ||
322 | usbv->speed); | ||
323 | |||
324 | dev_dbg(dev, "%s [%d](%p)\n", __func__, | ||
325 | usbhsh_device_number(hpriv, udev), udev); | ||
326 | |||
327 | return udev; | ||
328 | } | ||
329 | |||
330 | static void usbhsh_device_free(struct usbhsh_hpriv *hpriv, | ||
331 | struct usbhsh_device *udev) | ||
332 | { | ||
333 | struct usb_hcd *hcd = usbhsh_hpriv_to_hcd(hpriv); | ||
334 | struct device *dev = usbhsh_hcd_to_dev(hcd); | ||
335 | struct usb_device *usbv = usbhsh_udev_to_usbv(udev); | ||
336 | |||
337 | dev_dbg(dev, "%s [%d](%p)\n", __func__, | ||
338 | usbhsh_device_number(hpriv, udev), udev); | ||
339 | |||
340 | if (usbhsh_device_has_endpoint(udev)) | ||
341 | dev_warn(dev, "udev still have endpoint\n"); | ||
342 | |||
343 | /* | ||
344 | * usbhsh_usbv_to_udev() | ||
345 | * usbhsh_udev_to_usbv() | ||
346 | * will be disable | ||
347 | */ | ||
348 | dev_set_drvdata(&usbv->dev, NULL); | ||
349 | udev->usbv = NULL; | ||
350 | } | ||
351 | |||
352 | /* | ||
353 | * end-point control | ||
354 | */ | ||
355 | struct usbhsh_ep *usbhsh_endpoint_alloc(struct usbhsh_hpriv *hpriv, | ||
356 | struct usbhsh_device *udev, | ||
357 | struct usb_host_endpoint *ep, | ||
358 | int dir_in_req, | ||
359 | gfp_t mem_flags) | ||
360 | { | ||
361 | struct usbhs_priv *priv = usbhsh_hpriv_to_priv(hpriv); | ||
362 | struct usb_hcd *hcd = usbhsh_hpriv_to_hcd(hpriv); | ||
363 | struct usbhsh_ep *uep; | ||
364 | struct usbhsh_pipe_info *info; | ||
365 | struct usbhs_pipe *pipe, *best_pipe; | ||
366 | struct device *dev = usbhsh_hcd_to_dev(hcd); | ||
367 | struct usb_endpoint_descriptor *desc = &ep->desc; | ||
368 | int type, i, dir_in; | ||
369 | unsigned int min_usr; | ||
370 | |||
371 | dir_in_req = !!dir_in_req; | ||
372 | |||
373 | uep = kzalloc(sizeof(struct usbhsh_ep), mem_flags); | ||
374 | if (!uep) { | ||
375 | dev_err(dev, "usbhsh_ep alloc fail\n"); | ||
376 | return NULL; | ||
377 | } | ||
378 | |||
379 | if (usb_endpoint_xfer_control(desc)) { | ||
380 | best_pipe = usbhsh_hpriv_to_dcp(hpriv); | ||
381 | goto usbhsh_endpoint_alloc_find_pipe; | ||
382 | } | ||
383 | |||
384 | /* | ||
385 | * find best pipe for endpoint | ||
386 | * see | ||
387 | * HARDWARE LIMITATION | ||
388 | */ | ||
389 | type = usb_endpoint_type(desc); | ||
390 | min_usr = ~0; | ||
391 | best_pipe = NULL; | ||
392 | usbhs_for_each_pipe(pipe, priv, i) { | ||
393 | if (!usbhs_pipe_type_is(pipe, type)) | ||
394 | continue; | ||
395 | |||
396 | dir_in = !!usbhs_pipe_is_dir_in(pipe); | ||
397 | if (0 != (dir_in - dir_in_req)) | ||
398 | continue; | ||
399 | |||
400 | info = usbhsh_pipe_info(pipe); | ||
401 | |||
402 | if (min_usr > info->usr_cnt) { | ||
403 | min_usr = info->usr_cnt; | ||
404 | best_pipe = pipe; | ||
405 | } | ||
406 | } | ||
407 | |||
408 | if (unlikely(!best_pipe)) { | ||
409 | dev_err(dev, "couldn't find best pipe\n"); | ||
410 | kfree(uep); | ||
411 | return NULL; | ||
412 | } | ||
413 | usbhsh_endpoint_alloc_find_pipe: | ||
414 | /* | ||
415 | * init uep | ||
416 | */ | ||
417 | uep->pipe = best_pipe; | ||
418 | uep->maxp = usb_endpoint_maxp(desc); | ||
419 | usbhsh_uep_to_udev(uep) = udev; | ||
420 | usbhsh_ep_to_uep(ep) = uep; | ||
421 | |||
422 | /* | ||
423 | * update pipe user count | ||
424 | */ | ||
425 | info = usbhsh_pipe_info(best_pipe); | ||
426 | info->usr_cnt++; | ||
427 | |||
428 | /* init this endpoint, and attach it to udev */ | ||
429 | INIT_LIST_HEAD(&uep->ep_list); | ||
430 | list_add_tail(&uep->ep_list, &udev->ep_list_head); | ||
431 | |||
432 | /* | ||
433 | * usbhs_pipe_config_update() should be called after | ||
434 | * usbhs_device_config() | ||
435 | * see | ||
436 | * DCPMAXP/PIPEMAXP | ||
437 | */ | ||
438 | usbhs_pipe_sequence_data0(uep->pipe); | ||
439 | usbhs_pipe_config_update(uep->pipe, | ||
440 | usbhsh_device_number(hpriv, udev), | ||
441 | usb_endpoint_num(desc), | ||
442 | uep->maxp); | ||
443 | |||
444 | dev_dbg(dev, "%s [%d-%s](%p)\n", __func__, | ||
445 | usbhsh_device_number(hpriv, udev), | ||
446 | usbhs_pipe_name(uep->pipe), uep); | ||
447 | |||
448 | return uep; | ||
449 | } | ||
450 | |||
451 | void usbhsh_endpoint_free(struct usbhsh_hpriv *hpriv, | ||
452 | struct usb_host_endpoint *ep) | ||
453 | { | ||
454 | struct usbhs_priv *priv = usbhsh_hpriv_to_priv(hpriv); | ||
455 | struct device *dev = usbhs_priv_to_dev(priv); | ||
456 | struct usbhsh_ep *uep = usbhsh_ep_to_uep(ep); | ||
457 | struct usbhsh_pipe_info *info; | ||
458 | |||
459 | if (!uep) | ||
460 | return; | ||
461 | |||
462 | dev_dbg(dev, "%s [%d-%s](%p)\n", __func__, | ||
463 | usbhsh_device_number(hpriv, usbhsh_uep_to_udev(uep)), | ||
464 | usbhs_pipe_name(uep->pipe), uep); | ||
465 | |||
466 | info = usbhsh_pipe_info(uep->pipe); | ||
467 | info->usr_cnt--; | ||
468 | |||
469 | /* remove this endpoint from udev */ | ||
470 | list_del_init(&uep->ep_list); | ||
471 | |||
472 | usbhsh_uep_to_udev(uep) = NULL; | ||
473 | usbhsh_ep_to_uep(ep) = NULL; | ||
474 | |||
475 | kfree(uep); | ||
476 | } | ||
477 | |||
478 | /* | ||
479 | * queue push/pop | ||
480 | */ | ||
481 | static void usbhsh_queue_done(struct usbhs_priv *priv, struct usbhs_pkt *pkt) | ||
482 | { | ||
483 | struct usbhsh_request *ureq = usbhsh_pkt_to_req(pkt); | ||
484 | struct usbhsh_hpriv *hpriv = usbhsh_priv_to_hpriv(priv); | ||
485 | struct usb_hcd *hcd = usbhsh_hpriv_to_hcd(hpriv); | ||
486 | struct urb *urb = ureq->urb; | ||
487 | struct device *dev = usbhs_priv_to_dev(priv); | ||
488 | |||
489 | dev_dbg(dev, "%s\n", __func__); | ||
490 | |||
491 | if (!urb) { | ||
492 | dev_warn(dev, "pkt doesn't have urb\n"); | ||
493 | return; | ||
494 | } | ||
495 | |||
496 | urb->actual_length = pkt->actual; | ||
497 | usbhsh_req_free(hpriv, ureq); | ||
498 | usbhsh_urb_to_ureq(urb) = NULL; | ||
499 | |||
500 | usb_hcd_unlink_urb_from_ep(hcd, urb); | ||
501 | usb_hcd_giveback_urb(hcd, urb, 0); | ||
502 | } | ||
503 | |||
504 | static int usbhsh_queue_push(struct usb_hcd *hcd, | ||
505 | struct usbhs_pipe *pipe, | ||
506 | struct urb *urb) | ||
507 | { | ||
508 | struct usbhsh_request *ureq = usbhsh_urb_to_ureq(urb); | ||
509 | struct usbhs_pkt *pkt = &ureq->pkt; | ||
510 | struct device *dev = usbhsh_hcd_to_dev(hcd); | ||
511 | void *buf; | ||
512 | int len; | ||
513 | |||
514 | if (usb_pipeisoc(urb->pipe)) { | ||
515 | dev_err(dev, "pipe iso is not supported now\n"); | ||
516 | return -EIO; | ||
517 | } | ||
518 | |||
519 | if (usb_pipein(urb->pipe)) | ||
520 | pipe->handler = &usbhs_fifo_pio_pop_handler; | ||
521 | else | ||
522 | pipe->handler = &usbhs_fifo_pio_push_handler; | ||
523 | |||
524 | buf = (void *)(urb->transfer_buffer + urb->actual_length); | ||
525 | len = urb->transfer_buffer_length - urb->actual_length; | ||
526 | |||
527 | dev_dbg(dev, "%s\n", __func__); | ||
528 | usbhs_pkt_push(pipe, pkt, usbhsh_queue_done, | ||
529 | buf, len, (urb->transfer_flags & URB_ZERO_PACKET)); | ||
530 | usbhs_pkt_start(pipe); | ||
531 | |||
532 | return 0; | ||
533 | } | ||
534 | |||
535 | /* | ||
536 | * DCP setup stage | ||
537 | */ | ||
538 | static int usbhsh_is_request_address(struct urb *urb) | ||
539 | { | ||
540 | struct usb_ctrlrequest *cmd; | ||
541 | |||
542 | cmd = (struct usb_ctrlrequest *)urb->setup_packet; | ||
543 | |||
544 | if ((DeviceOutRequest == cmd->bRequestType << 8) && | ||
545 | (USB_REQ_SET_ADDRESS == cmd->bRequest)) | ||
546 | return 1; | ||
547 | else | ||
548 | return 0; | ||
549 | } | ||
550 | |||
551 | static void usbhsh_setup_stage_packet_push(struct usbhsh_hpriv *hpriv, | ||
552 | struct urb *urb, | ||
553 | struct usbhs_pipe *pipe) | ||
554 | { | ||
555 | struct usbhs_priv *priv = usbhsh_hpriv_to_priv(hpriv); | ||
556 | struct usb_ctrlrequest req; | ||
557 | struct device *dev = usbhs_priv_to_dev(priv); | ||
558 | |||
559 | /* | ||
560 | * wait setup packet ACK | ||
561 | * see | ||
562 | * usbhsh_irq_setup_ack() | ||
563 | * usbhsh_irq_setup_err() | ||
564 | */ | ||
565 | init_completion(&hpriv->setup_ack_done); | ||
566 | |||
567 | /* copy original request */ | ||
568 | memcpy(&req, urb->setup_packet, sizeof(struct usb_ctrlrequest)); | ||
569 | |||
570 | /* | ||
571 | * renesas_usbhs can not use original usb address. | ||
572 | * see HARDWARE LIMITATION. | ||
573 | * modify usb address here. | ||
574 | */ | ||
575 | if (usbhsh_is_request_address(urb)) { | ||
576 | /* FIXME */ | ||
577 | req.wValue = 1; | ||
578 | dev_dbg(dev, "create new address - %d\n", req.wValue); | ||
579 | } | ||
580 | |||
581 | /* set request */ | ||
582 | usbhs_usbreq_set_val(priv, &req); | ||
583 | |||
584 | /* | ||
585 | * wait setup packet ACK | ||
586 | */ | ||
587 | wait_for_completion(&hpriv->setup_ack_done); | ||
588 | |||
589 | dev_dbg(dev, "%s done\n", __func__); | ||
590 | } | ||
591 | |||
592 | /* | ||
593 | * DCP data stage | ||
594 | */ | ||
595 | static void usbhsh_data_stage_packet_done(struct usbhs_priv *priv, | ||
596 | struct usbhs_pkt *pkt) | ||
597 | { | ||
598 | struct usbhsh_request *ureq = usbhsh_pkt_to_req(pkt); | ||
599 | struct usbhsh_hpriv *hpriv = usbhsh_priv_to_hpriv(priv); | ||
600 | struct urb *urb = ureq->urb; | ||
601 | |||
602 | /* this ureq was connected to urb when usbhsh_urb_enqueue() */ | ||
603 | |||
604 | usbhsh_req_free(hpriv, ureq); | ||
605 | usbhsh_urb_to_ureq(urb) = NULL; | ||
606 | } | ||
607 | |||
608 | static void usbhsh_data_stage_packet_push(struct usbhsh_hpriv *hpriv, | ||
609 | struct urb *urb, | ||
610 | struct usbhs_pipe *pipe) | ||
611 | { | ||
612 | struct usbhsh_request *ureq; | ||
613 | struct usbhs_pkt *pkt; | ||
614 | |||
615 | /* | ||
616 | * FIXME | ||
617 | * | ||
618 | * data stage uses ureq which is connected to urb | ||
619 | * see usbhsh_urb_enqueue() :: alloc new request. | ||
620 | * it will be freed in usbhsh_data_stage_packet_done() | ||
621 | */ | ||
622 | ureq = usbhsh_urb_to_ureq(urb); | ||
623 | pkt = &ureq->pkt; | ||
624 | |||
625 | if (usb_pipein(urb->pipe)) | ||
626 | pipe->handler = &usbhs_dcp_data_stage_in_handler; | ||
627 | else | ||
628 | pipe->handler = &usbhs_dcp_data_stage_out_handler; | ||
629 | |||
630 | usbhs_pkt_push(pipe, pkt, | ||
631 | usbhsh_data_stage_packet_done, | ||
632 | urb->transfer_buffer, | ||
633 | urb->transfer_buffer_length, | ||
634 | (urb->transfer_flags & URB_ZERO_PACKET)); | ||
635 | } | ||
636 | |||
637 | /* | ||
638 | * DCP status stage | ||
639 | */ | ||
640 | static void usbhsh_status_stage_packet_push(struct usbhsh_hpriv *hpriv, | ||
641 | struct urb *urb, | ||
642 | struct usbhs_pipe *pipe) | ||
643 | { | ||
644 | struct usbhsh_request *ureq; | ||
645 | struct usbhs_pkt *pkt; | ||
646 | |||
647 | /* | ||
648 | * FIXME | ||
649 | * | ||
650 | * status stage uses allocated ureq. | ||
651 | * it will be freed on usbhsh_queue_done() | ||
652 | */ | ||
653 | ureq = usbhsh_req_alloc(hpriv, urb, GFP_KERNEL); | ||
654 | pkt = &ureq->pkt; | ||
655 | |||
656 | if (usb_pipein(urb->pipe)) | ||
657 | pipe->handler = &usbhs_dcp_status_stage_in_handler; | ||
658 | else | ||
659 | pipe->handler = &usbhs_dcp_status_stage_out_handler; | ||
660 | |||
661 | usbhs_pkt_push(pipe, pkt, | ||
662 | usbhsh_queue_done, | ||
663 | NULL, | ||
664 | urb->transfer_buffer_length, | ||
665 | 0); | ||
666 | } | ||
667 | |||
668 | static int usbhsh_dcp_queue_push(struct usb_hcd *hcd, | ||
669 | struct usbhsh_hpriv *hpriv, | ||
670 | struct usbhs_pipe *pipe, | ||
671 | struct urb *urb) | ||
672 | { | ||
673 | struct device *dev = usbhsh_hcd_to_dev(hcd); | ||
674 | |||
675 | dev_dbg(dev, "%s\n", __func__); | ||
676 | |||
677 | /* | ||
678 | * setup stage | ||
679 | * | ||
680 | * usbhsh_send_setup_stage_packet() wait SACK/SIGN | ||
681 | */ | ||
682 | usbhsh_setup_stage_packet_push(hpriv, urb, pipe); | ||
683 | |||
684 | /* | ||
685 | * data stage | ||
686 | * | ||
687 | * It is pushed only when urb has buffer. | ||
688 | */ | ||
689 | if (urb->transfer_buffer_length) | ||
690 | usbhsh_data_stage_packet_push(hpriv, urb, pipe); | ||
691 | |||
692 | /* | ||
693 | * status stage | ||
694 | */ | ||
695 | usbhsh_status_stage_packet_push(hpriv, urb, pipe); | ||
696 | |||
697 | /* | ||
698 | * start pushed packets | ||
699 | */ | ||
700 | usbhs_pkt_start(pipe); | ||
701 | |||
702 | return 0; | ||
703 | } | ||
704 | |||
705 | /* | ||
706 | * dma map functions | ||
707 | */ | ||
708 | static int usbhsh_dma_map_ctrl(struct usbhs_pkt *pkt, int map) | ||
709 | { | ||
710 | return 0; | ||
711 | } | ||
712 | |||
713 | /* | ||
714 | * for hc_driver | ||
715 | */ | ||
716 | static int usbhsh_host_start(struct usb_hcd *hcd) | ||
717 | { | ||
718 | return 0; | ||
719 | } | ||
720 | |||
721 | static void usbhsh_host_stop(struct usb_hcd *hcd) | ||
722 | { | ||
723 | } | ||
724 | |||
725 | static int usbhsh_urb_enqueue(struct usb_hcd *hcd, | ||
726 | struct urb *urb, | ||
727 | gfp_t mem_flags) | ||
728 | { | ||
729 | struct usbhsh_hpriv *hpriv = usbhsh_hcd_to_hpriv(hcd); | ||
730 | struct usbhs_priv *priv = usbhsh_hpriv_to_priv(hpriv); | ||
731 | struct device *dev = usbhs_priv_to_dev(priv); | ||
732 | struct usb_device *usbv = usbhsh_urb_to_usbv(urb); | ||
733 | struct usb_host_endpoint *ep = urb->ep; | ||
734 | struct usbhsh_request *ureq; | ||
735 | struct usbhsh_device *udev, *new_udev = NULL; | ||
736 | struct usbhs_pipe *pipe; | ||
737 | struct usbhsh_ep *uep; | ||
738 | int is_dir_in = usb_pipein(urb->pipe); | ||
739 | |||
740 | int ret; | ||
741 | |||
742 | dev_dbg(dev, "%s (%s)\n", __func__, is_dir_in ? "in" : "out"); | ||
743 | |||
744 | ret = usb_hcd_link_urb_to_ep(hcd, urb); | ||
745 | if (ret) | ||
746 | goto usbhsh_urb_enqueue_error_not_linked; | ||
747 | |||
748 | /* | ||
749 | * get udev | ||
750 | */ | ||
751 | udev = usbhsh_usbv_to_udev(usbv); | ||
752 | if (!udev) { | ||
753 | new_udev = usbhsh_device_alloc(hpriv, urb); | ||
754 | if (!new_udev) | ||
755 | goto usbhsh_urb_enqueue_error_not_linked; | ||
756 | |||
757 | udev = new_udev; | ||
758 | } | ||
759 | |||
760 | /* | ||
761 | * get uep | ||
762 | */ | ||
763 | uep = usbhsh_ep_to_uep(ep); | ||
764 | if (!uep) { | ||
765 | uep = usbhsh_endpoint_alloc(hpriv, udev, ep, | ||
766 | is_dir_in, mem_flags); | ||
767 | if (!uep) | ||
768 | goto usbhsh_urb_enqueue_error_free_device; | ||
769 | } | ||
770 | pipe = usbhsh_uep_to_pipe(uep); | ||
771 | |||
772 | /* | ||
773 | * alloc new request | ||
774 | */ | ||
775 | ureq = usbhsh_req_alloc(hpriv, urb, mem_flags); | ||
776 | if (unlikely(!ureq)) { | ||
777 | ret = -ENOMEM; | ||
778 | goto usbhsh_urb_enqueue_error_free_endpoint; | ||
779 | } | ||
780 | usbhsh_urb_to_ureq(urb) = ureq; | ||
781 | |||
782 | /* | ||
783 | * push packet | ||
784 | */ | ||
785 | if (usb_pipecontrol(urb->pipe)) | ||
786 | usbhsh_dcp_queue_push(hcd, hpriv, pipe, urb); | ||
787 | else | ||
788 | usbhsh_queue_push(hcd, pipe, urb); | ||
789 | |||
790 | return 0; | ||
791 | |||
792 | usbhsh_urb_enqueue_error_free_endpoint: | ||
793 | usbhsh_endpoint_free(hpriv, ep); | ||
794 | usbhsh_urb_enqueue_error_free_device: | ||
795 | if (new_udev) | ||
796 | usbhsh_device_free(hpriv, new_udev); | ||
797 | usbhsh_urb_enqueue_error_not_linked: | ||
798 | |||
799 | dev_dbg(dev, "%s error\n", __func__); | ||
800 | |||
801 | return ret; | ||
802 | } | ||
803 | |||
804 | static int usbhsh_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) | ||
805 | { | ||
806 | struct usbhsh_hpriv *hpriv = usbhsh_hcd_to_hpriv(hcd); | ||
807 | struct usbhsh_request *ureq = usbhsh_urb_to_ureq(urb); | ||
808 | |||
809 | if (ureq) { | ||
810 | usbhsh_req_free(hpriv, ureq); | ||
811 | usbhsh_urb_to_ureq(urb) = NULL; | ||
812 | } | ||
813 | |||
814 | return 0; | ||
815 | } | ||
816 | |||
817 | static void usbhsh_endpoint_disable(struct usb_hcd *hcd, | ||
818 | struct usb_host_endpoint *ep) | ||
819 | { | ||
820 | struct usbhsh_ep *uep = usbhsh_ep_to_uep(ep); | ||
821 | struct usbhsh_device *udev; | ||
822 | struct usbhsh_hpriv *hpriv; | ||
823 | |||
824 | /* | ||
825 | * this function might be called manytimes by same hcd/ep | ||
826 | * in-endpoitn == out-endpoint if ep == dcp. | ||
827 | */ | ||
828 | if (!uep) | ||
829 | return; | ||
830 | |||
831 | udev = usbhsh_uep_to_udev(uep); | ||
832 | hpriv = usbhsh_hcd_to_hpriv(hcd); | ||
833 | |||
834 | usbhsh_endpoint_free(hpriv, ep); | ||
835 | ep->hcpriv = NULL; | ||
836 | |||
837 | /* | ||
838 | * if there is no endpoint, | ||
839 | * free device | ||
840 | */ | ||
841 | if (!usbhsh_device_has_endpoint(udev)) | ||
842 | usbhsh_device_free(hpriv, udev); | ||
843 | } | ||
844 | |||
845 | static int usbhsh_hub_status_data(struct usb_hcd *hcd, char *buf) | ||
846 | { | ||
847 | struct usbhsh_hpriv *hpriv = usbhsh_hcd_to_hpriv(hcd); | ||
848 | struct usbhs_priv *priv = usbhsh_hpriv_to_priv(hpriv); | ||
849 | struct device *dev = usbhs_priv_to_dev(priv); | ||
850 | int roothub_id = 1; /* only 1 root hub */ | ||
851 | |||
852 | /* | ||
853 | * does port stat was changed ? | ||
854 | * check USB_PORT_STAT_C_xxx << 16 | ||
855 | */ | ||
856 | if (usbhsh_port_stat_get(hpriv) & 0xFFFF0000) | ||
857 | *buf = (1 << roothub_id); | ||
858 | else | ||
859 | *buf = 0; | ||
860 | |||
861 | dev_dbg(dev, "%s (%02x)\n", __func__, *buf); | ||
862 | |||
863 | return !!(*buf); | ||
864 | } | ||
865 | |||
866 | static int __usbhsh_hub_hub_feature(struct usbhsh_hpriv *hpriv, | ||
867 | u16 typeReq, u16 wValue, | ||
868 | u16 wIndex, char *buf, u16 wLength) | ||
869 | { | ||
870 | struct usbhs_priv *priv = usbhsh_hpriv_to_priv(hpriv); | ||
871 | struct device *dev = usbhs_priv_to_dev(priv); | ||
872 | |||
873 | switch (wValue) { | ||
874 | case C_HUB_OVER_CURRENT: | ||
875 | case C_HUB_LOCAL_POWER: | ||
876 | dev_dbg(dev, "%s :: C_HUB_xx\n", __func__); | ||
877 | return 0; | ||
878 | } | ||
879 | |||
880 | return -EPIPE; | ||
881 | } | ||
882 | |||
883 | static int __usbhsh_hub_port_feature(struct usbhsh_hpriv *hpriv, | ||
884 | u16 typeReq, u16 wValue, | ||
885 | u16 wIndex, char *buf, u16 wLength) | ||
886 | { | ||
887 | struct usbhs_priv *priv = usbhsh_hpriv_to_priv(hpriv); | ||
888 | struct device *dev = usbhs_priv_to_dev(priv); | ||
889 | int enable = (typeReq == SetPortFeature); | ||
890 | int speed, i, timeout = 128; | ||
891 | int roothub_id = 1; /* only 1 root hub */ | ||
892 | |||
893 | /* common error */ | ||
894 | if (wIndex > roothub_id || wLength != 0) | ||
895 | return -EPIPE; | ||
896 | |||
897 | /* check wValue */ | ||
898 | switch (wValue) { | ||
899 | case USB_PORT_FEAT_POWER: | ||
900 | usbhs_vbus_ctrl(priv, enable); | ||
901 | dev_dbg(dev, "%s :: USB_PORT_FEAT_POWER\n", __func__); | ||
902 | break; | ||
903 | |||
904 | case USB_PORT_FEAT_ENABLE: | ||
905 | case USB_PORT_FEAT_SUSPEND: | ||
906 | case USB_PORT_FEAT_C_ENABLE: | ||
907 | case USB_PORT_FEAT_C_SUSPEND: | ||
908 | case USB_PORT_FEAT_C_CONNECTION: | ||
909 | case USB_PORT_FEAT_C_OVER_CURRENT: | ||
910 | case USB_PORT_FEAT_C_RESET: | ||
911 | dev_dbg(dev, "%s :: USB_PORT_FEAT_xxx\n", __func__); | ||
912 | break; | ||
913 | |||
914 | case USB_PORT_FEAT_RESET: | ||
915 | if (!enable) | ||
916 | break; | ||
917 | |||
918 | usbhsh_port_stat_clear(hpriv, | ||
919 | USB_PORT_STAT_HIGH_SPEED | | ||
920 | USB_PORT_STAT_LOW_SPEED); | ||
921 | |||
922 | usbhs_bus_send_reset(priv); | ||
923 | msleep(20); | ||
924 | usbhs_bus_send_sof_enable(priv); | ||
925 | |||
926 | for (i = 0; i < timeout ; i++) { | ||
927 | switch (usbhs_bus_get_speed(priv)) { | ||
928 | case USB_SPEED_LOW: | ||
929 | speed = USB_PORT_STAT_LOW_SPEED; | ||
930 | goto got_usb_bus_speed; | ||
931 | case USB_SPEED_HIGH: | ||
932 | speed = USB_PORT_STAT_HIGH_SPEED; | ||
933 | goto got_usb_bus_speed; | ||
934 | case USB_SPEED_FULL: | ||
935 | speed = 0; | ||
936 | goto got_usb_bus_speed; | ||
937 | } | ||
938 | |||
939 | msleep(20); | ||
940 | } | ||
941 | return -EPIPE; | ||
942 | |||
943 | got_usb_bus_speed: | ||
944 | usbhsh_port_stat_set(hpriv, speed); | ||
945 | usbhsh_port_stat_set(hpriv, USB_PORT_STAT_ENABLE); | ||
946 | |||
947 | dev_dbg(dev, "%s :: USB_PORT_FEAT_RESET (speed = %d)\n", | ||
948 | __func__, speed); | ||
949 | |||
950 | /* status change is not needed */ | ||
951 | return 0; | ||
952 | |||
953 | default: | ||
954 | return -EPIPE; | ||
955 | } | ||
956 | |||
957 | /* set/clear status */ | ||
958 | if (enable) | ||
959 | usbhsh_port_stat_set(hpriv, (1 << wValue)); | ||
960 | else | ||
961 | usbhsh_port_stat_clear(hpriv, (1 << wValue)); | ||
962 | |||
963 | return 0; | ||
964 | } | ||
965 | |||
966 | static int __usbhsh_hub_get_status(struct usbhsh_hpriv *hpriv, | ||
967 | u16 typeReq, u16 wValue, | ||
968 | u16 wIndex, char *buf, u16 wLength) | ||
969 | { | ||
970 | struct usbhs_priv *priv = usbhsh_hpriv_to_priv(hpriv); | ||
971 | struct usb_hub_descriptor *desc = (struct usb_hub_descriptor *)buf; | ||
972 | struct device *dev = usbhs_priv_to_dev(priv); | ||
973 | int roothub_id = 1; /* only 1 root hub */ | ||
974 | |||
975 | switch (typeReq) { | ||
976 | case GetHubStatus: | ||
977 | dev_dbg(dev, "%s :: GetHubStatus\n", __func__); | ||
978 | |||
979 | *buf = 0x00; | ||
980 | break; | ||
981 | |||
982 | case GetPortStatus: | ||
983 | if (wIndex != roothub_id) | ||
984 | return -EPIPE; | ||
985 | |||
986 | dev_dbg(dev, "%s :: GetPortStatus\n", __func__); | ||
987 | *(__le32 *)buf = cpu_to_le32(usbhsh_port_stat_get(hpriv)); | ||
988 | break; | ||
989 | |||
990 | case GetHubDescriptor: | ||
991 | desc->bDescriptorType = 0x29; | ||
992 | desc->bHubContrCurrent = 0; | ||
993 | desc->bNbrPorts = roothub_id; | ||
994 | desc->bDescLength = 9; | ||
995 | desc->bPwrOn2PwrGood = 0; | ||
996 | desc->wHubCharacteristics = cpu_to_le16(0x0011); | ||
997 | desc->u.hs.DeviceRemovable[0] = (roothub_id << 1); | ||
998 | desc->u.hs.DeviceRemovable[1] = ~0; | ||
999 | dev_dbg(dev, "%s :: GetHubDescriptor\n", __func__); | ||
1000 | break; | ||
1001 | } | ||
1002 | |||
1003 | return 0; | ||
1004 | } | ||
1005 | |||
1006 | static int usbhsh_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | ||
1007 | u16 wIndex, char *buf, u16 wLength) | ||
1008 | { | ||
1009 | struct usbhsh_hpriv *hpriv = usbhsh_hcd_to_hpriv(hcd); | ||
1010 | struct usbhs_priv *priv = usbhsh_hpriv_to_priv(hpriv); | ||
1011 | struct device *dev = usbhs_priv_to_dev(priv); | ||
1012 | int ret = -EPIPE; | ||
1013 | |||
1014 | switch (typeReq) { | ||
1015 | |||
1016 | /* Hub Feature */ | ||
1017 | case ClearHubFeature: | ||
1018 | case SetHubFeature: | ||
1019 | ret = __usbhsh_hub_hub_feature(hpriv, typeReq, | ||
1020 | wValue, wIndex, buf, wLength); | ||
1021 | break; | ||
1022 | |||
1023 | /* Port Feature */ | ||
1024 | case SetPortFeature: | ||
1025 | case ClearPortFeature: | ||
1026 | ret = __usbhsh_hub_port_feature(hpriv, typeReq, | ||
1027 | wValue, wIndex, buf, wLength); | ||
1028 | break; | ||
1029 | |||
1030 | /* Get status */ | ||
1031 | case GetHubStatus: | ||
1032 | case GetPortStatus: | ||
1033 | case GetHubDescriptor: | ||
1034 | ret = __usbhsh_hub_get_status(hpriv, typeReq, | ||
1035 | wValue, wIndex, buf, wLength); | ||
1036 | break; | ||
1037 | } | ||
1038 | |||
1039 | dev_dbg(dev, "typeReq = %x, ret = %d, port_stat = %x\n", | ||
1040 | typeReq, ret, usbhsh_port_stat_get(hpriv)); | ||
1041 | |||
1042 | return ret; | ||
1043 | } | ||
1044 | |||
1045 | static struct hc_driver usbhsh_driver = { | ||
1046 | .description = usbhsh_hcd_name, | ||
1047 | .hcd_priv_size = sizeof(struct usbhsh_hpriv), | ||
1048 | |||
1049 | /* | ||
1050 | * generic hardware linkage | ||
1051 | */ | ||
1052 | .flags = HCD_USB2, | ||
1053 | |||
1054 | .start = usbhsh_host_start, | ||
1055 | .stop = usbhsh_host_stop, | ||
1056 | |||
1057 | /* | ||
1058 | * managing i/o requests and associated device resources | ||
1059 | */ | ||
1060 | .urb_enqueue = usbhsh_urb_enqueue, | ||
1061 | .urb_dequeue = usbhsh_urb_dequeue, | ||
1062 | .endpoint_disable = usbhsh_endpoint_disable, | ||
1063 | |||
1064 | /* | ||
1065 | * root hub | ||
1066 | */ | ||
1067 | .hub_status_data = usbhsh_hub_status_data, | ||
1068 | .hub_control = usbhsh_hub_control, | ||
1069 | }; | ||
1070 | |||
1071 | /* | ||
1072 | * interrupt functions | ||
1073 | */ | ||
1074 | static int usbhsh_irq_attch(struct usbhs_priv *priv, | ||
1075 | struct usbhs_irq_state *irq_state) | ||
1076 | { | ||
1077 | struct usbhsh_hpriv *hpriv = usbhsh_priv_to_hpriv(priv); | ||
1078 | struct device *dev = usbhs_priv_to_dev(priv); | ||
1079 | |||
1080 | dev_dbg(dev, "device attached\n"); | ||
1081 | |||
1082 | usbhsh_port_stat_set(hpriv, USB_PORT_STAT_CONNECTION); | ||
1083 | usbhsh_port_stat_set(hpriv, USB_PORT_STAT_C_CONNECTION << 16); | ||
1084 | |||
1085 | return 0; | ||
1086 | } | ||
1087 | |||
1088 | static int usbhsh_irq_dtch(struct usbhs_priv *priv, | ||
1089 | struct usbhs_irq_state *irq_state) | ||
1090 | { | ||
1091 | struct usbhsh_hpriv *hpriv = usbhsh_priv_to_hpriv(priv); | ||
1092 | struct device *dev = usbhs_priv_to_dev(priv); | ||
1093 | |||
1094 | dev_dbg(dev, "device detached\n"); | ||
1095 | |||
1096 | usbhsh_port_stat_clear(hpriv, USB_PORT_STAT_CONNECTION); | ||
1097 | usbhsh_port_stat_set(hpriv, USB_PORT_STAT_C_CONNECTION << 16); | ||
1098 | |||
1099 | return 0; | ||
1100 | } | ||
1101 | |||
1102 | static int usbhsh_irq_setup_ack(struct usbhs_priv *priv, | ||
1103 | struct usbhs_irq_state *irq_state) | ||
1104 | { | ||
1105 | struct usbhsh_hpriv *hpriv = usbhsh_priv_to_hpriv(priv); | ||
1106 | struct device *dev = usbhs_priv_to_dev(priv); | ||
1107 | |||
1108 | dev_dbg(dev, "setup packet OK\n"); | ||
1109 | |||
1110 | complete(&hpriv->setup_ack_done); /* see usbhsh_urb_enqueue() */ | ||
1111 | |||
1112 | return 0; | ||
1113 | } | ||
1114 | |||
1115 | static int usbhsh_irq_setup_err(struct usbhs_priv *priv, | ||
1116 | struct usbhs_irq_state *irq_state) | ||
1117 | { | ||
1118 | struct usbhsh_hpriv *hpriv = usbhsh_priv_to_hpriv(priv); | ||
1119 | struct device *dev = usbhs_priv_to_dev(priv); | ||
1120 | |||
1121 | dev_dbg(dev, "setup packet Err\n"); | ||
1122 | |||
1123 | complete(&hpriv->setup_ack_done); /* see usbhsh_urb_enqueue() */ | ||
1124 | |||
1125 | return 0; | ||
1126 | } | ||
1127 | |||
1128 | /* | ||
1129 | * module start/stop | ||
1130 | */ | ||
1131 | static void usbhsh_pipe_init_for_host(struct usbhs_priv *priv) | ||
1132 | { | ||
1133 | struct usbhsh_hpriv *hpriv = usbhsh_priv_to_hpriv(priv); | ||
1134 | struct usbhsh_pipe_info *pipe_info = hpriv->pipe_info; | ||
1135 | struct usbhs_pipe *pipe; | ||
1136 | u32 *pipe_type = usbhs_get_dparam(priv, pipe_type); | ||
1137 | int pipe_size = usbhs_get_dparam(priv, pipe_size); | ||
1138 | int old_type, dir_in, i; | ||
1139 | |||
1140 | /* init all pipe */ | ||
1141 | old_type = USB_ENDPOINT_XFER_CONTROL; | ||
1142 | for (i = 0; i < pipe_size; i++) { | ||
1143 | pipe_info[i].usr_cnt = 0; | ||
1144 | |||
1145 | /* | ||
1146 | * data "output" will be finished as soon as possible, | ||
1147 | * but there is no guaranty at data "input" case. | ||
1148 | * | ||
1149 | * "input" needs "standby" pipe. | ||
1150 | * So, "input" direction pipe > "output" direction pipe | ||
1151 | * is good idea. | ||
1152 | * | ||
1153 | * 1st USB_ENDPOINT_XFER_xxx will be output direction, | ||
1154 | * and the other will be input direction here. | ||
1155 | * | ||
1156 | * ex) | ||
1157 | * ... | ||
1158 | * USB_ENDPOINT_XFER_ISOC -> dir out | ||
1159 | * USB_ENDPOINT_XFER_ISOC -> dir in | ||
1160 | * USB_ENDPOINT_XFER_BULK -> dir out | ||
1161 | * USB_ENDPOINT_XFER_BULK -> dir in | ||
1162 | * USB_ENDPOINT_XFER_BULK -> dir in | ||
1163 | * ... | ||
1164 | */ | ||
1165 | dir_in = (pipe_type[i] == old_type); | ||
1166 | old_type = pipe_type[i]; | ||
1167 | |||
1168 | if (USB_ENDPOINT_XFER_CONTROL == pipe_type[i]) { | ||
1169 | pipe = usbhs_dcp_malloc(priv); | ||
1170 | usbhsh_hpriv_to_dcp(hpriv) = pipe; | ||
1171 | } else { | ||
1172 | pipe = usbhs_pipe_malloc(priv, | ||
1173 | pipe_type[i], | ||
1174 | dir_in); | ||
1175 | } | ||
1176 | |||
1177 | pipe->mod_private = pipe_info + i; | ||
1178 | } | ||
1179 | } | ||
1180 | |||
1181 | static int usbhsh_start(struct usbhs_priv *priv) | ||
1182 | { | ||
1183 | struct usbhsh_hpriv *hpriv = usbhsh_priv_to_hpriv(priv); | ||
1184 | struct usb_hcd *hcd = usbhsh_hpriv_to_hcd(hpriv); | ||
1185 | struct usbhs_mod *mod = usbhs_mod_get_current(priv); | ||
1186 | struct device *dev = usbhs_priv_to_dev(priv); | ||
1187 | int ret; | ||
1188 | |||
1189 | /* add hcd */ | ||
1190 | ret = usb_add_hcd(hcd, 0, 0); | ||
1191 | if (ret < 0) | ||
1192 | return 0; | ||
1193 | |||
1194 | /* | ||
1195 | * pipe initialize and enable DCP | ||
1196 | */ | ||
1197 | usbhs_pipe_init(priv, | ||
1198 | usbhsh_dma_map_ctrl); | ||
1199 | usbhs_fifo_init(priv); | ||
1200 | usbhsh_pipe_init_for_host(priv); | ||
1201 | |||
1202 | /* | ||
1203 | * system config enble | ||
1204 | * - HI speed | ||
1205 | * - host | ||
1206 | * - usb module | ||
1207 | */ | ||
1208 | usbhs_sys_hispeed_ctrl(priv, 1); | ||
1209 | usbhs_sys_host_ctrl(priv, 1); | ||
1210 | usbhs_sys_usb_ctrl(priv, 1); | ||
1211 | |||
1212 | /* | ||
1213 | * enable irq callback | ||
1214 | */ | ||
1215 | mod->irq_attch = usbhsh_irq_attch; | ||
1216 | mod->irq_dtch = usbhsh_irq_dtch; | ||
1217 | mod->irq_sack = usbhsh_irq_setup_ack; | ||
1218 | mod->irq_sign = usbhsh_irq_setup_err; | ||
1219 | usbhs_irq_callback_update(priv, mod); | ||
1220 | |||
1221 | dev_dbg(dev, "start host\n"); | ||
1222 | |||
1223 | return ret; | ||
1224 | } | ||
1225 | |||
1226 | static int usbhsh_stop(struct usbhs_priv *priv) | ||
1227 | { | ||
1228 | struct usbhsh_hpriv *hpriv = usbhsh_priv_to_hpriv(priv); | ||
1229 | struct usb_hcd *hcd = usbhsh_hpriv_to_hcd(hpriv); | ||
1230 | struct usbhs_mod *mod = usbhs_mod_get_current(priv); | ||
1231 | struct device *dev = usbhs_priv_to_dev(priv); | ||
1232 | |||
1233 | /* | ||
1234 | * disable irq callback | ||
1235 | */ | ||
1236 | mod->irq_attch = NULL; | ||
1237 | mod->irq_dtch = NULL; | ||
1238 | mod->irq_sack = NULL; | ||
1239 | mod->irq_sign = NULL; | ||
1240 | usbhs_irq_callback_update(priv, mod); | ||
1241 | |||
1242 | usb_remove_hcd(hcd); | ||
1243 | |||
1244 | /* disable sys */ | ||
1245 | usbhs_sys_hispeed_ctrl(priv, 0); | ||
1246 | usbhs_sys_host_ctrl(priv, 0); | ||
1247 | usbhs_sys_usb_ctrl(priv, 0); | ||
1248 | |||
1249 | dev_dbg(dev, "quit host\n"); | ||
1250 | |||
1251 | return 0; | ||
1252 | } | ||
1253 | |||
1254 | int usbhs_mod_host_probe(struct usbhs_priv *priv) | ||
1255 | { | ||
1256 | struct usbhsh_hpriv *hpriv; | ||
1257 | struct usb_hcd *hcd; | ||
1258 | struct usbhsh_pipe_info *pipe_info; | ||
1259 | struct usbhsh_device *udev; | ||
1260 | struct device *dev = usbhs_priv_to_dev(priv); | ||
1261 | int pipe_size = usbhs_get_dparam(priv, pipe_size); | ||
1262 | int i; | ||
1263 | |||
1264 | /* initialize hcd */ | ||
1265 | hcd = usb_create_hcd(&usbhsh_driver, dev, usbhsh_hcd_name); | ||
1266 | if (!hcd) { | ||
1267 | dev_err(dev, "Failed to create hcd\n"); | ||
1268 | return -ENOMEM; | ||
1269 | } | ||
1270 | |||
1271 | pipe_info = kzalloc(sizeof(*pipe_info) * pipe_size, GFP_KERNEL); | ||
1272 | if (!pipe_info) { | ||
1273 | dev_err(dev, "Could not allocate pipe_info\n"); | ||
1274 | goto usbhs_mod_host_probe_err; | ||
1275 | } | ||
1276 | |||
1277 | /* | ||
1278 | * CAUTION | ||
1279 | * | ||
1280 | * There is no guarantee that it is possible to access usb module here. | ||
1281 | * Don't accesses to it. | ||
1282 | * The accesse will be enable after "usbhsh_start" | ||
1283 | */ | ||
1284 | |||
1285 | hpriv = usbhsh_hcd_to_hpriv(hcd); | ||
1286 | |||
1287 | /* | ||
1288 | * register itself | ||
1289 | */ | ||
1290 | usbhs_mod_register(priv, &hpriv->mod, USBHS_HOST); | ||
1291 | |||
1292 | /* init hpriv */ | ||
1293 | hpriv->mod.name = "host"; | ||
1294 | hpriv->mod.start = usbhsh_start; | ||
1295 | hpriv->mod.stop = usbhsh_stop; | ||
1296 | hpriv->pipe_info = pipe_info; | ||
1297 | hpriv->pipe_size = pipe_size; | ||
1298 | usbhsh_req_list_init(hpriv); | ||
1299 | usbhsh_port_stat_init(hpriv); | ||
1300 | |||
1301 | /* init all device */ | ||
1302 | usbhsh_for_each_udev_with_dev0(udev, hpriv, i) { | ||
1303 | udev->usbv = NULL; | ||
1304 | INIT_LIST_HEAD(&udev->ep_list_head); | ||
1305 | } | ||
1306 | |||
1307 | dev_info(dev, "host probed\n"); | ||
1308 | |||
1309 | return 0; | ||
1310 | |||
1311 | usbhs_mod_host_probe_err: | ||
1312 | usb_put_hcd(hcd); | ||
1313 | |||
1314 | return -ENOMEM; | ||
1315 | } | ||
1316 | |||
1317 | int usbhs_mod_host_remove(struct usbhs_priv *priv) | ||
1318 | { | ||
1319 | struct usbhsh_hpriv *hpriv = usbhsh_priv_to_hpriv(priv); | ||
1320 | struct usb_hcd *hcd = usbhsh_hpriv_to_hcd(hpriv); | ||
1321 | |||
1322 | usbhsh_req_list_quit(hpriv); | ||
1323 | |||
1324 | usb_put_hcd(hcd); | ||
1325 | |||
1326 | return 0; | ||
1327 | } | ||
diff --git a/drivers/usb/renesas_usbhs/pipe.c b/drivers/usb/renesas_usbhs/pipe.c index 1b14cae45704..c74389ce2177 100644 --- a/drivers/usb/renesas_usbhs/pipe.c +++ b/drivers/usb/renesas_usbhs/pipe.c | |||
@@ -29,9 +29,6 @@ | |||
29 | #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) |
30 | #define usbhsp_flags_init(p) do {(p)->flags = 0; } while (0) | 30 | #define usbhsp_flags_init(p) do {(p)->flags = 0; } while (0) |
31 | 31 | ||
32 | #define usbhsp_type(p) ((p)->pipe_type) | ||
33 | #define usbhsp_type_is(p, t) ((p)->pipe_type == t) | ||
34 | |||
35 | /* | 32 | /* |
36 | * for debug | 33 | * for debug |
37 | */ | 34 | */ |
@@ -42,28 +39,9 @@ static char *usbhsp_pipe_name[] = { | |||
42 | [USB_ENDPOINT_XFER_ISOC] = "ISO", | 39 | [USB_ENDPOINT_XFER_ISOC] = "ISO", |
43 | }; | 40 | }; |
44 | 41 | ||
45 | /* | 42 | char *usbhs_pipe_name(struct usbhs_pipe *pipe) |
46 | * usb request functions | ||
47 | */ | ||
48 | void usbhs_usbreq_get_val(struct usbhs_priv *priv, struct usb_ctrlrequest *req) | ||
49 | { | 43 | { |
50 | u16 val; | 44 | return usbhsp_pipe_name[usbhs_pipe_type(pipe)]; |
51 | |||
52 | val = usbhs_read(priv, USBREQ); | ||
53 | req->bRequest = (val >> 8) & 0xFF; | ||
54 | req->bRequestType = (val >> 0) & 0xFF; | ||
55 | |||
56 | req->wValue = usbhs_read(priv, USBVAL); | ||
57 | req->wIndex = usbhs_read(priv, USBINDX); | ||
58 | req->wLength = usbhs_read(priv, USBLENG); | ||
59 | } | ||
60 | |||
61 | void usbhs_usbreq_set_val(struct usbhs_priv *priv, struct usb_ctrlrequest *req) | ||
62 | { | ||
63 | usbhs_write(priv, USBREQ, (req->bRequest << 8) | req->bRequestType); | ||
64 | usbhs_write(priv, USBVAL, req->wValue); | ||
65 | usbhs_write(priv, USBINDX, req->wIndex); | ||
66 | usbhs_write(priv, USBLENG, req->wLength); | ||
67 | } | 45 | } |
68 | 46 | ||
69 | /* | 47 | /* |
@@ -106,17 +84,6 @@ static void __usbhsp_pipe_xxx_set(struct usbhs_pipe *pipe, | |||
106 | usbhs_bset(priv, pipe_reg, mask, val); | 84 | usbhs_bset(priv, pipe_reg, mask, val); |
107 | } | 85 | } |
108 | 86 | ||
109 | static u16 __usbhsp_pipe_xxx_get(struct usbhs_pipe *pipe, | ||
110 | u16 dcp_reg, u16 pipe_reg) | ||
111 | { | ||
112 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | ||
113 | |||
114 | if (usbhs_pipe_is_dcp(pipe)) | ||
115 | return usbhs_read(priv, dcp_reg); | ||
116 | else | ||
117 | return usbhs_read(priv, pipe_reg); | ||
118 | } | ||
119 | |||
120 | /* | 87 | /* |
121 | * DCPCFG/PIPECFG functions | 88 | * DCPCFG/PIPECFG functions |
122 | */ | 89 | */ |
@@ -144,11 +111,6 @@ static void usbhsp_pipe_maxp_set(struct usbhs_pipe *pipe, u16 mask, u16 val) | |||
144 | __usbhsp_pipe_xxx_set(pipe, DCPMAXP, PIPEMAXP, mask, val); | 111 | __usbhsp_pipe_xxx_set(pipe, DCPMAXP, PIPEMAXP, mask, val); |
145 | } | 112 | } |
146 | 113 | ||
147 | static u16 usbhsp_pipe_maxp_get(struct usbhs_pipe *pipe) | ||
148 | { | ||
149 | return __usbhsp_pipe_xxx_get(pipe, DCPMAXP, PIPEMAXP); | ||
150 | } | ||
151 | |||
152 | /* | 114 | /* |
153 | * pipe control functions | 115 | * pipe control functions |
154 | */ | 116 | */ |
@@ -303,16 +265,16 @@ static int usbhsp_possible_double_buffer(struct usbhs_pipe *pipe) | |||
303 | /* | 265 | /* |
304 | * only ISO / BULK pipe can use double buffer | 266 | * only ISO / BULK pipe can use double buffer |
305 | */ | 267 | */ |
306 | if (usbhsp_type_is(pipe, USB_ENDPOINT_XFER_BULK) || | 268 | if (usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_BULK) || |
307 | usbhsp_type_is(pipe, USB_ENDPOINT_XFER_ISOC)) | 269 | usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_ISOC)) |
308 | return 1; | 270 | return 1; |
309 | 271 | ||
310 | return 0; | 272 | return 0; |
311 | } | 273 | } |
312 | 274 | ||
313 | static u16 usbhsp_setup_pipecfg(struct usbhs_pipe *pipe, | 275 | static u16 usbhsp_setup_pipecfg(struct usbhs_pipe *pipe, |
314 | const struct usb_endpoint_descriptor *desc, | 276 | int is_host, |
315 | int is_host) | 277 | int dir_in) |
316 | { | 278 | { |
317 | u16 type = 0; | 279 | u16 type = 0; |
318 | u16 bfre = 0; | 280 | u16 bfre = 0; |
@@ -341,40 +303,40 @@ static u16 usbhsp_setup_pipecfg(struct usbhs_pipe *pipe, | |||
341 | */ | 303 | */ |
342 | 304 | ||
343 | /* TYPE */ | 305 | /* TYPE */ |
344 | type = type_array[usbhsp_type(pipe)]; | 306 | type = type_array[usbhs_pipe_type(pipe)]; |
345 | 307 | ||
346 | /* BFRE */ | 308 | /* BFRE */ |
347 | if (usbhsp_type_is(pipe, USB_ENDPOINT_XFER_ISOC) || | 309 | if (usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_ISOC) || |
348 | usbhsp_type_is(pipe, USB_ENDPOINT_XFER_BULK)) | 310 | usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_BULK)) |
349 | bfre = 0; /* FIXME */ | 311 | bfre = 0; /* FIXME */ |
350 | 312 | ||
351 | /* DBLB */ | 313 | /* DBLB */ |
352 | if (usbhsp_type_is(pipe, USB_ENDPOINT_XFER_ISOC) || | 314 | if (usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_ISOC) || |
353 | usbhsp_type_is(pipe, USB_ENDPOINT_XFER_BULK)) | 315 | usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_BULK)) |
354 | dblb = (is_double) ? DBLB : 0; | 316 | dblb = (is_double) ? DBLB : 0; |
355 | 317 | ||
356 | /* CNTMD */ | 318 | /* CNTMD */ |
357 | if (usbhsp_type_is(pipe, USB_ENDPOINT_XFER_BULK)) | 319 | if (usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_BULK)) |
358 | cntmd = 0; /* FIXME */ | 320 | cntmd = 0; /* FIXME */ |
359 | 321 | ||
360 | /* DIR */ | 322 | /* DIR */ |
361 | if (usb_endpoint_dir_in(desc)) | 323 | if (dir_in) |
362 | usbhsp_flags_set(pipe, IS_DIR_HOST); | 324 | usbhsp_flags_set(pipe, IS_DIR_HOST); |
363 | 325 | ||
364 | if ((is_host && usb_endpoint_dir_out(desc)) || | 326 | if ((is_host && !dir_in) || |
365 | (!is_host && usb_endpoint_dir_in(desc))) | 327 | (!is_host && dir_in)) |
366 | dir |= DIR_OUT; | 328 | dir |= DIR_OUT; |
367 | 329 | ||
368 | if (!dir) | 330 | if (!dir) |
369 | usbhsp_flags_set(pipe, IS_DIR_IN); | 331 | usbhsp_flags_set(pipe, IS_DIR_IN); |
370 | 332 | ||
371 | /* SHTNAK */ | 333 | /* SHTNAK */ |
372 | if (usbhsp_type_is(pipe, USB_ENDPOINT_XFER_BULK) && | 334 | if (usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_BULK) && |
373 | !dir) | 335 | !dir) |
374 | shtnak = SHTNAK; | 336 | shtnak = SHTNAK; |
375 | 337 | ||
376 | /* EPNUM */ | 338 | /* EPNUM */ |
377 | epnum = 0xF & usb_endpoint_num(desc); | 339 | epnum = 0; /* see usbhs_pipe_config_update() */ |
378 | 340 | ||
379 | return type | | 341 | return type | |
380 | bfre | | 342 | bfre | |
@@ -385,19 +347,7 @@ static u16 usbhsp_setup_pipecfg(struct usbhs_pipe *pipe, | |||
385 | epnum; | 347 | epnum; |
386 | } | 348 | } |
387 | 349 | ||
388 | static u16 usbhsp_setup_pipemaxp(struct usbhs_pipe *pipe, | 350 | static u16 usbhsp_setup_pipebuff(struct usbhs_pipe *pipe) |
389 | const struct usb_endpoint_descriptor *desc, | ||
390 | int is_host) | ||
391 | { | ||
392 | /* host should set DEVSEL */ | ||
393 | |||
394 | /* reutn MXPS */ | ||
395 | return PIPE_MAXP_MASK & le16_to_cpu(desc->wMaxPacketSize); | ||
396 | } | ||
397 | |||
398 | static u16 usbhsp_setup_pipebuff(struct usbhs_pipe *pipe, | ||
399 | const struct usb_endpoint_descriptor *desc, | ||
400 | int is_host) | ||
401 | { | 351 | { |
402 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | 352 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); |
403 | struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv); | 353 | struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv); |
@@ -441,9 +391,9 @@ static u16 usbhsp_setup_pipebuff(struct usbhs_pipe *pipe, | |||
441 | * INT : 64 byte | 391 | * INT : 64 byte |
442 | * ISOC: 512 byte | 392 | * ISOC: 512 byte |
443 | */ | 393 | */ |
444 | if (usbhsp_type_is(pipe, USB_ENDPOINT_XFER_CONTROL)) | 394 | if (usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_CONTROL)) |
445 | buff_size = 256; | 395 | buff_size = 256; |
446 | else if (usbhsp_type_is(pipe, USB_ENDPOINT_XFER_INT)) | 396 | else if (usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_INT)) |
447 | buff_size = 64; | 397 | buff_size = 64; |
448 | else | 398 | else |
449 | buff_size = 512; | 399 | buff_size = 512; |
@@ -453,7 +403,7 @@ static u16 usbhsp_setup_pipebuff(struct usbhs_pipe *pipe, | |||
453 | 403 | ||
454 | /* BUFNMB has been reserved for INT pipe | 404 | /* BUFNMB has been reserved for INT pipe |
455 | * see above */ | 405 | * see above */ |
456 | if (usbhsp_type_is(pipe, USB_ENDPOINT_XFER_INT)) { | 406 | if (usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_INT)) { |
457 | bufnmb = pipe_num - 2; | 407 | bufnmb = pipe_num - 2; |
458 | } else { | 408 | } else { |
459 | bufnmb = info->bufnmb_last; | 409 | bufnmb = info->bufnmb_last; |
@@ -473,16 +423,42 @@ static u16 usbhsp_setup_pipebuff(struct usbhs_pipe *pipe, | |||
473 | (0xff & bufnmb) << 0; | 423 | (0xff & bufnmb) << 0; |
474 | } | 424 | } |
475 | 425 | ||
426 | void usbhs_pipe_config_update(struct usbhs_pipe *pipe, u16 devsel, | ||
427 | u16 epnum, u16 maxp) | ||
428 | { | ||
429 | if (devsel > 0xA) { | ||
430 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | ||
431 | struct device *dev = usbhs_priv_to_dev(priv); | ||
432 | |||
433 | dev_err(dev, "devsel error %d\n", devsel); | ||
434 | |||
435 | devsel = 0; | ||
436 | } | ||
437 | |||
438 | usbhsp_pipe_barrier(pipe); | ||
439 | |||
440 | pipe->maxp = maxp; | ||
441 | |||
442 | usbhsp_pipe_select(pipe); | ||
443 | usbhsp_pipe_maxp_set(pipe, 0xFFFF, | ||
444 | (devsel << 12) | | ||
445 | maxp); | ||
446 | |||
447 | if (!usbhs_pipe_is_dcp(pipe)) | ||
448 | usbhsp_pipe_cfg_set(pipe, 0x000F, epnum); | ||
449 | } | ||
450 | |||
476 | /* | 451 | /* |
477 | * pipe control | 452 | * pipe control |
478 | */ | 453 | */ |
479 | int usbhs_pipe_get_maxpacket(struct usbhs_pipe *pipe) | 454 | int usbhs_pipe_get_maxpacket(struct usbhs_pipe *pipe) |
480 | { | 455 | { |
481 | u16 mask = usbhs_pipe_is_dcp(pipe) ? DCP_MAXP_MASK : PIPE_MAXP_MASK; | 456 | /* |
482 | 457 | * see | |
483 | usbhsp_pipe_select(pipe); | 458 | * usbhs_pipe_config_update() |
484 | 459 | * usbhs_dcp_malloc() | |
485 | return (int)(usbhsp_pipe_maxp_get(pipe) & mask); | 460 | */ |
461 | return pipe->maxp; | ||
486 | } | 462 | } |
487 | 463 | ||
488 | int usbhs_pipe_is_dir_in(struct usbhs_pipe *pipe) | 464 | int usbhs_pipe_is_dir_in(struct usbhs_pipe *pipe) |
@@ -495,9 +471,12 @@ int usbhs_pipe_is_dir_host(struct usbhs_pipe *pipe) | |||
495 | return usbhsp_flags_has(pipe, IS_DIR_HOST); | 471 | return usbhsp_flags_has(pipe, IS_DIR_HOST); |
496 | } | 472 | } |
497 | 473 | ||
498 | void usbhs_pipe_clear_sequence(struct usbhs_pipe *pipe) | 474 | void usbhs_pipe_data_sequence(struct usbhs_pipe *pipe, int data) |
499 | { | 475 | { |
500 | usbhsp_pipectrl_set(pipe, SQCLR, SQCLR); | 476 | u16 mask = (SQCLR | SQSET); |
477 | u16 val = (data) ? SQSET : SQCLR; | ||
478 | |||
479 | usbhsp_pipectrl_set(pipe, mask, val); | ||
501 | } | 480 | } |
502 | 481 | ||
503 | void usbhs_pipe_clear(struct usbhs_pipe *pipe) | 482 | void usbhs_pipe_clear(struct usbhs_pipe *pipe) |
@@ -516,7 +495,7 @@ static struct usbhs_pipe *usbhsp_get_pipe(struct usbhs_priv *priv, u32 type) | |||
516 | */ | 495 | */ |
517 | pipe = NULL; | 496 | pipe = NULL; |
518 | usbhs_for_each_pipe_with_dcp(pos, priv, i) { | 497 | usbhs_for_each_pipe_with_dcp(pos, priv, i) { |
519 | if (!usbhsp_type_is(pos, type)) | 498 | if (!usbhs_pipe_type_is(pos, type)) |
520 | continue; | 499 | continue; |
521 | if (usbhsp_flags_has(pos, IS_USED)) | 500 | if (usbhsp_flags_has(pos, IS_USED)) |
522 | continue; | 501 | continue; |
@@ -538,19 +517,12 @@ static struct usbhs_pipe *usbhsp_get_pipe(struct usbhs_priv *priv, u32 type) | |||
538 | } | 517 | } |
539 | 518 | ||
540 | void usbhs_pipe_init(struct usbhs_priv *priv, | 519 | 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)) | 520 | int (*dma_map_ctrl)(struct usbhs_pkt *pkt, int map)) |
543 | { | 521 | { |
544 | struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv); | 522 | struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv); |
545 | struct device *dev = usbhs_priv_to_dev(priv); | ||
546 | struct usbhs_pipe *pipe; | 523 | struct usbhs_pipe *pipe; |
547 | int i; | 524 | int i; |
548 | 525 | ||
549 | if (!done) { | ||
550 | dev_err(dev, "no done function\n"); | ||
551 | return; | ||
552 | } | ||
553 | |||
554 | /* | 526 | /* |
555 | * FIXME | 527 | * FIXME |
556 | * | 528 | * |
@@ -565,7 +537,7 @@ void usbhs_pipe_init(struct usbhs_priv *priv, | |||
565 | */ | 537 | */ |
566 | info->bufnmb_last = 4; | 538 | info->bufnmb_last = 4; |
567 | usbhs_for_each_pipe_with_dcp(pipe, priv, i) { | 539 | usbhs_for_each_pipe_with_dcp(pipe, priv, i) { |
568 | if (usbhsp_type_is(pipe, USB_ENDPOINT_XFER_INT)) | 540 | if (usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_INT)) |
569 | info->bufnmb_last++; | 541 | info->bufnmb_last++; |
570 | 542 | ||
571 | usbhsp_flags_init(pipe); | 543 | usbhsp_flags_init(pipe); |
@@ -577,24 +549,23 @@ void usbhs_pipe_init(struct usbhs_priv *priv, | |||
577 | usbhs_pipe_clear(pipe); | 549 | usbhs_pipe_clear(pipe); |
578 | } | 550 | } |
579 | 551 | ||
580 | info->done = done; | ||
581 | info->dma_map_ctrl = dma_map_ctrl; | 552 | info->dma_map_ctrl = dma_map_ctrl; |
582 | } | 553 | } |
583 | 554 | ||
584 | struct usbhs_pipe *usbhs_pipe_malloc(struct usbhs_priv *priv, | 555 | struct usbhs_pipe *usbhs_pipe_malloc(struct usbhs_priv *priv, |
585 | const struct usb_endpoint_descriptor *desc) | 556 | int endpoint_type, |
557 | int dir_in) | ||
586 | { | 558 | { |
587 | struct device *dev = usbhs_priv_to_dev(priv); | 559 | struct device *dev = usbhs_priv_to_dev(priv); |
588 | struct usbhs_mod *mod = usbhs_mod_get_current(priv); | ||
589 | struct usbhs_pipe *pipe; | 560 | struct usbhs_pipe *pipe; |
590 | int is_host = usbhs_mod_is_host(priv, mod); | 561 | int is_host = usbhs_mod_is_host(priv); |
591 | int ret; | 562 | int ret; |
592 | u16 pipecfg, pipebuf, pipemaxp; | 563 | u16 pipecfg, pipebuf; |
593 | 564 | ||
594 | pipe = usbhsp_get_pipe(priv, usb_endpoint_type(desc)); | 565 | pipe = usbhsp_get_pipe(priv, endpoint_type); |
595 | if (!pipe) { | 566 | if (!pipe) { |
596 | dev_err(dev, "can't get pipe (%s)\n", | 567 | dev_err(dev, "can't get pipe (%s)\n", |
597 | usbhsp_pipe_name[usb_endpoint_type(desc)]); | 568 | usbhsp_pipe_name[endpoint_type]); |
598 | return NULL; | 569 | return NULL; |
599 | } | 570 | } |
600 | 571 | ||
@@ -609,22 +580,25 @@ struct usbhs_pipe *usbhs_pipe_malloc(struct usbhs_priv *priv, | |||
609 | return NULL; | 580 | return NULL; |
610 | } | 581 | } |
611 | 582 | ||
612 | pipecfg = usbhsp_setup_pipecfg(pipe, desc, is_host); | 583 | pipecfg = usbhsp_setup_pipecfg(pipe, is_host, dir_in); |
613 | pipebuf = usbhsp_setup_pipebuff(pipe, desc, is_host); | 584 | pipebuf = usbhsp_setup_pipebuff(pipe); |
614 | pipemaxp = usbhsp_setup_pipemaxp(pipe, desc, is_host); | ||
615 | 585 | ||
616 | usbhsp_pipe_select(pipe); | 586 | usbhsp_pipe_select(pipe); |
617 | usbhsp_pipe_cfg_set(pipe, 0xFFFF, pipecfg); | 587 | usbhsp_pipe_cfg_set(pipe, 0xFFFF, pipecfg); |
618 | usbhsp_pipe_buf_set(pipe, 0xFFFF, pipebuf); | 588 | usbhsp_pipe_buf_set(pipe, 0xFFFF, pipebuf); |
619 | usbhsp_pipe_maxp_set(pipe, 0xFFFF, pipemaxp); | ||
620 | 589 | ||
621 | usbhs_pipe_clear_sequence(pipe); | 590 | usbhs_pipe_sequence_data0(pipe); |
622 | 591 | ||
623 | dev_dbg(dev, "enable pipe %d : %s (%s)\n", | 592 | dev_dbg(dev, "enable pipe %d : %s (%s)\n", |
624 | usbhs_pipe_number(pipe), | 593 | usbhs_pipe_number(pipe), |
625 | usbhsp_pipe_name[usb_endpoint_type(desc)], | 594 | usbhs_pipe_name(pipe), |
626 | usbhs_pipe_is_dir_in(pipe) ? "in" : "out"); | 595 | usbhs_pipe_is_dir_in(pipe) ? "in" : "out"); |
627 | 596 | ||
597 | /* | ||
598 | * epnum / maxp are still not set to this pipe. | ||
599 | * call usbhs_pipe_config_update() after this function !! | ||
600 | */ | ||
601 | |||
628 | return pipe; | 602 | return pipe; |
629 | } | 603 | } |
630 | 604 | ||
@@ -651,25 +625,31 @@ struct usbhs_pipe *usbhs_dcp_malloc(struct usbhs_priv *priv) | |||
651 | if (!pipe) | 625 | if (!pipe) |
652 | return NULL; | 626 | return NULL; |
653 | 627 | ||
628 | INIT_LIST_HEAD(&pipe->list); | ||
629 | |||
654 | /* | 630 | /* |
655 | * dcpcfg : default | 631 | * call usbhs_pipe_config_update() after this function !! |
656 | * dcpmaxp : default | ||
657 | * pipebuf : nothing to do | ||
658 | */ | 632 | */ |
659 | 633 | ||
660 | usbhsp_pipe_select(pipe); | ||
661 | usbhs_pipe_clear_sequence(pipe); | ||
662 | INIT_LIST_HEAD(&pipe->list); | ||
663 | |||
664 | return pipe; | 634 | return pipe; |
665 | } | 635 | } |
666 | 636 | ||
667 | void usbhs_dcp_control_transfer_done(struct usbhs_pipe *pipe) | 637 | void usbhs_dcp_control_transfer_done(struct usbhs_pipe *pipe) |
668 | { | 638 | { |
639 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | ||
640 | |||
669 | WARN_ON(!usbhs_pipe_is_dcp(pipe)); | 641 | WARN_ON(!usbhs_pipe_is_dcp(pipe)); |
670 | 642 | ||
671 | usbhs_pipe_enable(pipe); | 643 | usbhs_pipe_enable(pipe); |
672 | usbhsp_pipectrl_set(pipe, CCPL, CCPL); | 644 | |
645 | if (!usbhs_mod_is_host(priv)) /* funconly */ | ||
646 | usbhsp_pipectrl_set(pipe, CCPL, CCPL); | ||
647 | } | ||
648 | |||
649 | void usbhs_dcp_dir_for_host(struct usbhs_pipe *pipe, int dir_out) | ||
650 | { | ||
651 | usbhsp_pipe_cfg_set(pipe, DIR_OUT, | ||
652 | dir_out ? DIR_OUT : 0); | ||
673 | } | 653 | } |
674 | 654 | ||
675 | /* | 655 | /* |
@@ -703,7 +683,9 @@ int usbhs_pipe_probe(struct usbhs_priv *priv) | |||
703 | */ | 683 | */ |
704 | usbhs_for_each_pipe_with_dcp(pipe, priv, i) { | 684 | usbhs_for_each_pipe_with_dcp(pipe, priv, i) { |
705 | pipe->priv = priv; | 685 | pipe->priv = priv; |
706 | usbhsp_type(pipe) = pipe_type[i] & USB_ENDPOINT_XFERTYPE_MASK; | 686 | |
687 | usbhs_pipe_type(pipe) = | ||
688 | pipe_type[i] & USB_ENDPOINT_XFERTYPE_MASK; | ||
707 | 689 | ||
708 | dev_dbg(dev, "pipe %x\t: %s\n", | 690 | dev_dbg(dev, "pipe %x\t: %s\n", |
709 | i, usbhsp_pipe_name[pipe_type[i]]); | 691 | i, usbhsp_pipe_name[pipe_type[i]]); |
diff --git a/drivers/usb/renesas_usbhs/pipe.h b/drivers/usb/renesas_usbhs/pipe.h index 41534cb0e734..6334fc644cc0 100644 --- a/drivers/usb/renesas_usbhs/pipe.h +++ b/drivers/usb/renesas_usbhs/pipe.h | |||
@@ -30,11 +30,15 @@ struct usbhs_pipe { | |||
30 | struct usbhs_fifo *fifo; | 30 | struct usbhs_fifo *fifo; |
31 | struct list_head list; | 31 | struct list_head list; |
32 | 32 | ||
33 | int maxp; | ||
34 | |||
33 | u32 flags; | 35 | u32 flags; |
34 | #define USBHS_PIPE_FLAGS_IS_USED (1 << 0) | 36 | #define USBHS_PIPE_FLAGS_IS_USED (1 << 0) |
35 | #define USBHS_PIPE_FLAGS_IS_DIR_IN (1 << 1) | 37 | #define USBHS_PIPE_FLAGS_IS_DIR_IN (1 << 1) |
36 | #define USBHS_PIPE_FLAGS_IS_DIR_HOST (1 << 2) | 38 | #define USBHS_PIPE_FLAGS_IS_DIR_HOST (1 << 2) |
37 | 39 | ||
40 | struct usbhs_pkt_handle *handler; | ||
41 | |||
38 | void *mod_private; | 42 | void *mod_private; |
39 | }; | 43 | }; |
40 | 44 | ||
@@ -43,7 +47,6 @@ struct usbhs_pipe_info { | |||
43 | int size; /* array size of "pipe" */ | 47 | int size; /* array size of "pipe" */ |
44 | int bufnmb_last; /* FIXME : driver needs good allocator */ | 48 | int bufnmb_last; /* FIXME : driver needs good allocator */ |
45 | 49 | ||
46 | void (*done)(struct usbhs_pkt *pkt); | ||
47 | int (*dma_map_ctrl)(struct usbhs_pkt *pkt, int map); | 50 | int (*dma_map_ctrl)(struct usbhs_pkt *pkt, int map); |
48 | }; | 51 | }; |
49 | 52 | ||
@@ -67,32 +70,30 @@ struct usbhs_pipe_info { | |||
67 | #define usbhs_priv_to_pipeinfo(pr) (&(pr)->pipe_info) | 70 | #define usbhs_priv_to_pipeinfo(pr) (&(pr)->pipe_info) |
68 | 71 | ||
69 | /* | 72 | /* |
70 | * usb request | ||
71 | */ | ||
72 | void usbhs_usbreq_get_val(struct usbhs_priv *priv, struct usb_ctrlrequest *req); | ||
73 | void usbhs_usbreq_set_val(struct usbhs_priv *priv, struct usb_ctrlrequest *req); | ||
74 | |||
75 | /* | ||
76 | * pipe control | 73 | * pipe control |
77 | */ | 74 | */ |
75 | char *usbhs_pipe_name(struct usbhs_pipe *pipe); | ||
78 | struct usbhs_pipe | 76 | struct usbhs_pipe |
79 | *usbhs_pipe_malloc(struct usbhs_priv *priv, | 77 | *usbhs_pipe_malloc(struct usbhs_priv *priv, int endpoint_type, int dir_in); |
80 | const struct usb_endpoint_descriptor *desc); | ||
81 | int usbhs_pipe_probe(struct usbhs_priv *priv); | 78 | int usbhs_pipe_probe(struct usbhs_priv *priv); |
82 | void usbhs_pipe_remove(struct usbhs_priv *priv); | 79 | void usbhs_pipe_remove(struct usbhs_priv *priv); |
83 | int usbhs_pipe_is_dir_in(struct usbhs_pipe *pipe); | 80 | int usbhs_pipe_is_dir_in(struct usbhs_pipe *pipe); |
84 | int usbhs_pipe_is_dir_host(struct usbhs_pipe *pipe); | 81 | int usbhs_pipe_is_dir_host(struct usbhs_pipe *pipe); |
85 | void usbhs_pipe_init(struct usbhs_priv *priv, | 82 | 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)); | 83 | int (*dma_map_ctrl)(struct usbhs_pkt *pkt, int map)); |
88 | int usbhs_pipe_get_maxpacket(struct usbhs_pipe *pipe); | 84 | int usbhs_pipe_get_maxpacket(struct usbhs_pipe *pipe); |
89 | void usbhs_pipe_clear_sequence(struct usbhs_pipe *pipe); | ||
90 | void usbhs_pipe_clear(struct usbhs_pipe *pipe); | 85 | void usbhs_pipe_clear(struct usbhs_pipe *pipe); |
91 | int usbhs_pipe_is_accessible(struct usbhs_pipe *pipe); | 86 | int usbhs_pipe_is_accessible(struct usbhs_pipe *pipe); |
92 | void usbhs_pipe_enable(struct usbhs_pipe *pipe); | 87 | void usbhs_pipe_enable(struct usbhs_pipe *pipe); |
93 | void usbhs_pipe_disable(struct usbhs_pipe *pipe); | 88 | void usbhs_pipe_disable(struct usbhs_pipe *pipe); |
94 | void usbhs_pipe_stall(struct usbhs_pipe *pipe); | 89 | void usbhs_pipe_stall(struct usbhs_pipe *pipe); |
95 | void usbhs_pipe_select_fifo(struct usbhs_pipe *pipe, struct usbhs_fifo *fifo); | 90 | void usbhs_pipe_select_fifo(struct usbhs_pipe *pipe, struct usbhs_fifo *fifo); |
91 | void usbhs_pipe_config_update(struct usbhs_pipe *pipe, u16 devsel, | ||
92 | u16 epnum, u16 maxp); | ||
93 | |||
94 | #define usbhs_pipe_sequence_data0(pipe) usbhs_pipe_data_sequence(pipe, 0) | ||
95 | #define usbhs_pipe_sequence_data1(pipe) usbhs_pipe_data_sequence(pipe, 1) | ||
96 | void usbhs_pipe_data_sequence(struct usbhs_pipe *pipe, int data); | ||
96 | 97 | ||
97 | #define usbhs_pipe_to_priv(p) ((p)->priv) | 98 | #define usbhs_pipe_to_priv(p) ((p)->priv) |
98 | #define usbhs_pipe_number(p) (int)((p) - (p)->priv->pipe_info.pipe) | 99 | #define usbhs_pipe_number(p) (int)((p) - (p)->priv->pipe_info.pipe) |
@@ -100,10 +101,14 @@ void usbhs_pipe_select_fifo(struct usbhs_pipe *pipe, struct usbhs_fifo *fifo); | |||
100 | #define usbhs_pipe_to_fifo(p) ((p)->fifo) | 101 | #define usbhs_pipe_to_fifo(p) ((p)->fifo) |
101 | #define usbhs_pipe_is_busy(p) usbhs_pipe_to_fifo(p) | 102 | #define usbhs_pipe_is_busy(p) usbhs_pipe_to_fifo(p) |
102 | 103 | ||
104 | #define usbhs_pipe_type(p) ((p)->pipe_type) | ||
105 | #define usbhs_pipe_type_is(p, t) ((p)->pipe_type == t) | ||
106 | |||
103 | /* | 107 | /* |
104 | * dcp control | 108 | * dcp control |
105 | */ | 109 | */ |
106 | struct usbhs_pipe *usbhs_dcp_malloc(struct usbhs_priv *priv); | 110 | struct usbhs_pipe *usbhs_dcp_malloc(struct usbhs_priv *priv); |
107 | void usbhs_dcp_control_transfer_done(struct usbhs_pipe *pipe); | 111 | void usbhs_dcp_control_transfer_done(struct usbhs_pipe *pipe); |
112 | void usbhs_dcp_dir_for_host(struct usbhs_pipe *pipe, int dir_out); | ||
108 | 113 | ||
109 | #endif /* RENESAS_USB_PIPE_H */ | 114 | #endif /* RENESAS_USB_PIPE_H */ |