diff options
Diffstat (limited to 'drivers/usb/chipidea')
-rw-r--r-- | drivers/usb/chipidea/Makefile | 1 | ||||
-rw-r--r-- | drivers/usb/chipidea/bits.h | 2 | ||||
-rw-r--r-- | drivers/usb/chipidea/ci.h | 2 | ||||
-rw-r--r-- | drivers/usb/chipidea/ci_hdrc_imx.c | 2 | ||||
-rw-r--r-- | drivers/usb/chipidea/ci_hdrc_zevio.c | 72 | ||||
-rw-r--r-- | drivers/usb/chipidea/core.c | 87 | ||||
-rw-r--r-- | drivers/usb/chipidea/udc.c | 324 |
7 files changed, 276 insertions, 214 deletions
diff --git a/drivers/usb/chipidea/Makefile b/drivers/usb/chipidea/Makefile index 7345d2115af2..480bd4d5710a 100644 --- a/drivers/usb/chipidea/Makefile +++ b/drivers/usb/chipidea/Makefile | |||
@@ -10,6 +10,7 @@ ci_hdrc-$(CONFIG_USB_CHIPIDEA_DEBUG) += debug.o | |||
10 | # Glue/Bridge layers go here | 10 | # Glue/Bridge layers go here |
11 | 11 | ||
12 | obj-$(CONFIG_USB_CHIPIDEA) += ci_hdrc_msm.o | 12 | obj-$(CONFIG_USB_CHIPIDEA) += ci_hdrc_msm.o |
13 | obj-$(CONFIG_USB_CHIPIDEA) += ci_hdrc_zevio.o | ||
13 | 14 | ||
14 | # PCI doesn't provide stubs, need to check | 15 | # PCI doesn't provide stubs, need to check |
15 | ifneq ($(CONFIG_PCI),) | 16 | ifneq ($(CONFIG_PCI),) |
diff --git a/drivers/usb/chipidea/bits.h b/drivers/usb/chipidea/bits.h index a85713165688..83d06c1455b7 100644 --- a/drivers/usb/chipidea/bits.h +++ b/drivers/usb/chipidea/bits.h | |||
@@ -50,12 +50,14 @@ | |||
50 | #define PORTSC_PTC (0x0FUL << 16) | 50 | #define PORTSC_PTC (0x0FUL << 16) |
51 | #define PORTSC_PHCD(d) ((d) ? BIT(22) : BIT(23)) | 51 | #define PORTSC_PHCD(d) ((d) ? BIT(22) : BIT(23)) |
52 | /* PTS and PTW for non lpm version only */ | 52 | /* PTS and PTW for non lpm version only */ |
53 | #define PORTSC_PFSC BIT(24) | ||
53 | #define PORTSC_PTS(d) \ | 54 | #define PORTSC_PTS(d) \ |
54 | (u32)((((d) & 0x3) << 30) | (((d) & 0x4) ? BIT(25) : 0)) | 55 | (u32)((((d) & 0x3) << 30) | (((d) & 0x4) ? BIT(25) : 0)) |
55 | #define PORTSC_PTW BIT(28) | 56 | #define PORTSC_PTW BIT(28) |
56 | #define PORTSC_STS BIT(29) | 57 | #define PORTSC_STS BIT(29) |
57 | 58 | ||
58 | /* DEVLC */ | 59 | /* DEVLC */ |
60 | #define DEVLC_PFSC BIT(23) | ||
59 | #define DEVLC_PSPD (0x03UL << 25) | 61 | #define DEVLC_PSPD (0x03UL << 25) |
60 | #define DEVLC_PSPD_HS (0x02UL << 25) | 62 | #define DEVLC_PSPD_HS (0x02UL << 25) |
61 | #define DEVLC_PTW BIT(27) | 63 | #define DEVLC_PTW BIT(27) |
diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h index 88b80f7728e4..e206406ae1d9 100644 --- a/drivers/usb/chipidea/ci.h +++ b/drivers/usb/chipidea/ci.h | |||
@@ -196,8 +196,6 @@ struct ci_hdrc { | |||
196 | 196 | ||
197 | struct ci_hdrc_platform_data *platdata; | 197 | struct ci_hdrc_platform_data *platdata; |
198 | int vbus_active; | 198 | int vbus_active; |
199 | /* FIXME: some day, we'll not use global phy */ | ||
200 | bool global_phy; | ||
201 | struct usb_phy *transceiver; | 199 | struct usb_phy *transceiver; |
202 | struct usb_hcd *hcd; | 200 | struct usb_hcd *hcd; |
203 | struct dentry *debugfs; | 201 | struct dentry *debugfs; |
diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c index c00f77257d36..2e58f8dfd311 100644 --- a/drivers/usb/chipidea/ci_hdrc_imx.c +++ b/drivers/usb/chipidea/ci_hdrc_imx.c | |||
@@ -96,7 +96,7 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev) | |||
96 | { | 96 | { |
97 | struct ci_hdrc_imx_data *data; | 97 | struct ci_hdrc_imx_data *data; |
98 | struct ci_hdrc_platform_data pdata = { | 98 | struct ci_hdrc_platform_data pdata = { |
99 | .name = "ci_hdrc_imx", | 99 | .name = dev_name(&pdev->dev), |
100 | .capoffset = DEF_CAPOFFSET, | 100 | .capoffset = DEF_CAPOFFSET, |
101 | .flags = CI_HDRC_REQUIRE_TRANSCEIVER | | 101 | .flags = CI_HDRC_REQUIRE_TRANSCEIVER | |
102 | CI_HDRC_DISABLE_STREAMING, | 102 | CI_HDRC_DISABLE_STREAMING, |
diff --git a/drivers/usb/chipidea/ci_hdrc_zevio.c b/drivers/usb/chipidea/ci_hdrc_zevio.c new file mode 100644 index 000000000000..3bf6489ef5ec --- /dev/null +++ b/drivers/usb/chipidea/ci_hdrc_zevio.c | |||
@@ -0,0 +1,72 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2013 Daniel Tang <tangrs@tangrs.id.au> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2, as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * Based off drivers/usb/chipidea/ci_hdrc_msm.c | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/platform_device.h> | ||
14 | #include <linux/usb/gadget.h> | ||
15 | #include <linux/usb/chipidea.h> | ||
16 | |||
17 | #include "ci.h" | ||
18 | |||
19 | static struct ci_hdrc_platform_data ci_hdrc_zevio_platdata = { | ||
20 | .name = "ci_hdrc_zevio", | ||
21 | .flags = CI_HDRC_REGS_SHARED, | ||
22 | .capoffset = DEF_CAPOFFSET, | ||
23 | }; | ||
24 | |||
25 | static int ci_hdrc_zevio_probe(struct platform_device *pdev) | ||
26 | { | ||
27 | struct platform_device *ci_pdev; | ||
28 | |||
29 | dev_dbg(&pdev->dev, "ci_hdrc_zevio_probe\n"); | ||
30 | |||
31 | ci_pdev = ci_hdrc_add_device(&pdev->dev, | ||
32 | pdev->resource, pdev->num_resources, | ||
33 | &ci_hdrc_zevio_platdata); | ||
34 | |||
35 | if (IS_ERR(ci_pdev)) { | ||
36 | dev_err(&pdev->dev, "ci_hdrc_add_device failed!\n"); | ||
37 | return PTR_ERR(ci_pdev); | ||
38 | } | ||
39 | |||
40 | platform_set_drvdata(pdev, ci_pdev); | ||
41 | |||
42 | return 0; | ||
43 | } | ||
44 | |||
45 | static int ci_hdrc_zevio_remove(struct platform_device *pdev) | ||
46 | { | ||
47 | struct platform_device *ci_pdev = platform_get_drvdata(pdev); | ||
48 | |||
49 | ci_hdrc_remove_device(ci_pdev); | ||
50 | |||
51 | return 0; | ||
52 | } | ||
53 | |||
54 | static const struct of_device_id ci_hdrc_zevio_dt_ids[] = { | ||
55 | { .compatible = "lsi,zevio-usb", }, | ||
56 | { /* sentinel */ } | ||
57 | }; | ||
58 | |||
59 | static struct platform_driver ci_hdrc_zevio_driver = { | ||
60 | .probe = ci_hdrc_zevio_probe, | ||
61 | .remove = ci_hdrc_zevio_remove, | ||
62 | .driver = { | ||
63 | .name = "zevio_usb", | ||
64 | .owner = THIS_MODULE, | ||
65 | .of_match_table = ci_hdrc_zevio_dt_ids, | ||
66 | }, | ||
67 | }; | ||
68 | |||
69 | MODULE_DEVICE_TABLE(of, ci_hdrc_zevio_dt_ids); | ||
70 | module_platform_driver(ci_hdrc_zevio_driver); | ||
71 | |||
72 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c index 33f22bc6ad7f..ca6831c5b763 100644 --- a/drivers/usb/chipidea/core.c +++ b/drivers/usb/chipidea/core.c | |||
@@ -64,6 +64,7 @@ | |||
64 | #include <linux/usb/otg.h> | 64 | #include <linux/usb/otg.h> |
65 | #include <linux/usb/chipidea.h> | 65 | #include <linux/usb/chipidea.h> |
66 | #include <linux/usb/of.h> | 66 | #include <linux/usb/of.h> |
67 | #include <linux/of.h> | ||
67 | #include <linux/phy.h> | 68 | #include <linux/phy.h> |
68 | #include <linux/regulator/consumer.h> | 69 | #include <linux/regulator/consumer.h> |
69 | 70 | ||
@@ -298,6 +299,13 @@ int hw_device_reset(struct ci_hdrc *ci, u32 mode) | |||
298 | if (ci->platdata->flags & CI_HDRC_DISABLE_STREAMING) | 299 | if (ci->platdata->flags & CI_HDRC_DISABLE_STREAMING) |
299 | hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS); | 300 | hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS); |
300 | 301 | ||
302 | if (ci->platdata->flags & CI_HDRC_FORCE_FULLSPEED) { | ||
303 | if (ci->hw_bank.lpm) | ||
304 | hw_write(ci, OP_DEVLC, DEVLC_PFSC, DEVLC_PFSC); | ||
305 | else | ||
306 | hw_write(ci, OP_PORTSC, PORTSC_PFSC, PORTSC_PFSC); | ||
307 | } | ||
308 | |||
301 | /* USBMODE should be configured step by step */ | 309 | /* USBMODE should be configured step by step */ |
302 | hw_write(ci, OP_USBMODE, USBMODE_CM, USBMODE_CM_IDLE); | 310 | hw_write(ci, OP_USBMODE, USBMODE_CM, USBMODE_CM_IDLE); |
303 | hw_write(ci, OP_USBMODE, USBMODE_CM, mode); | 311 | hw_write(ci, OP_USBMODE, USBMODE_CM, mode); |
@@ -412,6 +420,9 @@ static int ci_get_platdata(struct device *dev, | |||
412 | } | 420 | } |
413 | } | 421 | } |
414 | 422 | ||
423 | if (of_usb_get_maximum_speed(dev->of_node) == USB_SPEED_FULL) | ||
424 | platdata->flags |= CI_HDRC_FORCE_FULLSPEED; | ||
425 | |||
415 | return 0; | 426 | return 0; |
416 | } | 427 | } |
417 | 428 | ||
@@ -496,33 +507,6 @@ static void ci_get_otg_capable(struct ci_hdrc *ci) | |||
496 | } | 507 | } |
497 | } | 508 | } |
498 | 509 | ||
499 | static int ci_usb_phy_init(struct ci_hdrc *ci) | ||
500 | { | ||
501 | if (ci->platdata->phy) { | ||
502 | ci->transceiver = ci->platdata->phy; | ||
503 | return usb_phy_init(ci->transceiver); | ||
504 | } else { | ||
505 | ci->global_phy = true; | ||
506 | ci->transceiver = usb_get_phy(USB_PHY_TYPE_USB2); | ||
507 | if (IS_ERR(ci->transceiver)) | ||
508 | ci->transceiver = NULL; | ||
509 | |||
510 | return 0; | ||
511 | } | ||
512 | } | ||
513 | |||
514 | static void ci_usb_phy_destroy(struct ci_hdrc *ci) | ||
515 | { | ||
516 | if (!ci->transceiver) | ||
517 | return; | ||
518 | |||
519 | otg_set_peripheral(ci->transceiver->otg, NULL); | ||
520 | if (ci->global_phy) | ||
521 | usb_put_phy(ci->transceiver); | ||
522 | else | ||
523 | usb_phy_shutdown(ci->transceiver); | ||
524 | } | ||
525 | |||
526 | static int ci_hdrc_probe(struct platform_device *pdev) | 510 | static int ci_hdrc_probe(struct platform_device *pdev) |
527 | { | 511 | { |
528 | struct device *dev = &pdev->dev; | 512 | struct device *dev = &pdev->dev; |
@@ -532,7 +516,7 @@ static int ci_hdrc_probe(struct platform_device *pdev) | |||
532 | int ret; | 516 | int ret; |
533 | enum usb_dr_mode dr_mode; | 517 | enum usb_dr_mode dr_mode; |
534 | 518 | ||
535 | if (!dev->platform_data) { | 519 | if (!dev_get_platdata(dev)) { |
536 | dev_err(dev, "platform data missing\n"); | 520 | dev_err(dev, "platform data missing\n"); |
537 | return -ENODEV; | 521 | return -ENODEV; |
538 | } | 522 | } |
@@ -549,7 +533,7 @@ static int ci_hdrc_probe(struct platform_device *pdev) | |||
549 | } | 533 | } |
550 | 534 | ||
551 | ci->dev = dev; | 535 | ci->dev = dev; |
552 | ci->platdata = dev->platform_data; | 536 | ci->platdata = dev_get_platdata(dev); |
553 | ci->imx28_write_fix = !!(ci->platdata->flags & | 537 | ci->imx28_write_fix = !!(ci->platdata->flags & |
554 | CI_HDRC_IMX28_WRITE_FIX); | 538 | CI_HDRC_IMX28_WRITE_FIX); |
555 | 539 | ||
@@ -561,7 +545,26 @@ static int ci_hdrc_probe(struct platform_device *pdev) | |||
561 | 545 | ||
562 | hw_phymode_configure(ci); | 546 | hw_phymode_configure(ci); |
563 | 547 | ||
564 | ret = ci_usb_phy_init(ci); | 548 | if (ci->platdata->phy) |
549 | ci->transceiver = ci->platdata->phy; | ||
550 | else | ||
551 | ci->transceiver = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2); | ||
552 | |||
553 | if (IS_ERR(ci->transceiver)) { | ||
554 | ret = PTR_ERR(ci->transceiver); | ||
555 | /* | ||
556 | * if -ENXIO is returned, it means PHY layer wasn't | ||
557 | * enabled, so it makes no sense to return -EPROBE_DEFER | ||
558 | * in that case, since no PHY driver will ever probe. | ||
559 | */ | ||
560 | if (ret == -ENXIO) | ||
561 | return ret; | ||
562 | |||
563 | dev_err(dev, "no usb2 phy configured\n"); | ||
564 | return -EPROBE_DEFER; | ||
565 | } | ||
566 | |||
567 | ret = usb_phy_init(ci->transceiver); | ||
565 | if (ret) { | 568 | if (ret) { |
566 | dev_err(dev, "unable to init phy: %d\n", ret); | 569 | dev_err(dev, "unable to init phy: %d\n", ret); |
567 | return ret; | 570 | return ret; |
@@ -572,8 +575,8 @@ static int ci_hdrc_probe(struct platform_device *pdev) | |||
572 | ci->irq = platform_get_irq(pdev, 0); | 575 | ci->irq = platform_get_irq(pdev, 0); |
573 | if (ci->irq < 0) { | 576 | if (ci->irq < 0) { |
574 | dev_err(dev, "missing IRQ\n"); | 577 | dev_err(dev, "missing IRQ\n"); |
575 | ret = -ENODEV; | 578 | ret = ci->irq; |
576 | goto destroy_phy; | 579 | goto deinit_phy; |
577 | } | 580 | } |
578 | 581 | ||
579 | ci_get_otg_capable(ci); | 582 | ci_get_otg_capable(ci); |
@@ -590,23 +593,12 @@ static int ci_hdrc_probe(struct platform_device *pdev) | |||
590 | ret = ci_hdrc_gadget_init(ci); | 593 | ret = ci_hdrc_gadget_init(ci); |
591 | if (ret) | 594 | if (ret) |
592 | dev_info(dev, "doesn't support gadget\n"); | 595 | dev_info(dev, "doesn't support gadget\n"); |
593 | if (!ret && ci->transceiver) { | ||
594 | ret = otg_set_peripheral(ci->transceiver->otg, | ||
595 | &ci->gadget); | ||
596 | /* | ||
597 | * If we implement all USB functions using chipidea drivers, | ||
598 | * it doesn't need to call above API, meanwhile, if we only | ||
599 | * use gadget function, calling above API is useless. | ||
600 | */ | ||
601 | if (ret && ret != -ENOTSUPP) | ||
602 | goto destroy_phy; | ||
603 | } | ||
604 | } | 596 | } |
605 | 597 | ||
606 | if (!ci->roles[CI_ROLE_HOST] && !ci->roles[CI_ROLE_GADGET]) { | 598 | if (!ci->roles[CI_ROLE_HOST] && !ci->roles[CI_ROLE_GADGET]) { |
607 | dev_err(dev, "no supported roles\n"); | 599 | dev_err(dev, "no supported roles\n"); |
608 | ret = -ENODEV; | 600 | ret = -ENODEV; |
609 | goto destroy_phy; | 601 | goto deinit_phy; |
610 | } | 602 | } |
611 | 603 | ||
612 | if (ci->is_otg) { | 604 | if (ci->is_otg) { |
@@ -663,8 +655,8 @@ static int ci_hdrc_probe(struct platform_device *pdev) | |||
663 | free_irq(ci->irq, ci); | 655 | free_irq(ci->irq, ci); |
664 | stop: | 656 | stop: |
665 | ci_role_destroy(ci); | 657 | ci_role_destroy(ci); |
666 | destroy_phy: | 658 | deinit_phy: |
667 | ci_usb_phy_destroy(ci); | 659 | usb_phy_shutdown(ci->transceiver); |
668 | 660 | ||
669 | return ret; | 661 | return ret; |
670 | } | 662 | } |
@@ -677,7 +669,8 @@ static int ci_hdrc_remove(struct platform_device *pdev) | |||
677 | free_irq(ci->irq, ci); | 669 | free_irq(ci->irq, ci); |
678 | ci_role_destroy(ci); | 670 | ci_role_destroy(ci); |
679 | ci_hdrc_enter_lpm(ci, true); | 671 | ci_hdrc_enter_lpm(ci, true); |
680 | ci_usb_phy_destroy(ci); | 672 | usb_phy_shutdown(ci->transceiver); |
673 | kfree(ci->hw_bank.regmap); | ||
681 | 674 | ||
682 | return 0; | 675 | return 0; |
683 | } | 676 | } |
diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index 4ab2cb62dfce..7739c64ef259 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c | |||
@@ -178,19 +178,6 @@ static int hw_ep_get_halt(struct ci_hdrc *ci, int num, int dir) | |||
178 | } | 178 | } |
179 | 179 | ||
180 | /** | 180 | /** |
181 | * hw_test_and_clear_setup_status: test & clear setup status (execute without | ||
182 | * interruption) | ||
183 | * @n: endpoint number | ||
184 | * | ||
185 | * This function returns setup status | ||
186 | */ | ||
187 | static int hw_test_and_clear_setup_status(struct ci_hdrc *ci, int n) | ||
188 | { | ||
189 | n = ep_to_bit(ci, n); | ||
190 | return hw_test_and_clear(ci, OP_ENDPTSETUPSTAT, BIT(n)); | ||
191 | } | ||
192 | |||
193 | /** | ||
194 | * hw_ep_prime: primes endpoint (execute without interruption) | 181 | * hw_ep_prime: primes endpoint (execute without interruption) |
195 | * @num: endpoint number | 182 | * @num: endpoint number |
196 | * @dir: endpoint direction | 183 | * @dir: endpoint direction |
@@ -962,6 +949,156 @@ __acquires(hwep->lock) | |||
962 | } | 949 | } |
963 | 950 | ||
964 | /** | 951 | /** |
952 | * isr_setup_packet_handler: setup packet handler | ||
953 | * @ci: UDC descriptor | ||
954 | * | ||
955 | * This function handles setup packet | ||
956 | */ | ||
957 | static void isr_setup_packet_handler(struct ci_hdrc *ci) | ||
958 | __releases(ci->lock) | ||
959 | __acquires(ci->lock) | ||
960 | { | ||
961 | struct ci_hw_ep *hwep = &ci->ci_hw_ep[0]; | ||
962 | struct usb_ctrlrequest req; | ||
963 | int type, num, dir, err = -EINVAL; | ||
964 | u8 tmode = 0; | ||
965 | |||
966 | /* | ||
967 | * Flush data and handshake transactions of previous | ||
968 | * setup packet. | ||
969 | */ | ||
970 | _ep_nuke(ci->ep0out); | ||
971 | _ep_nuke(ci->ep0in); | ||
972 | |||
973 | /* read_setup_packet */ | ||
974 | do { | ||
975 | hw_test_and_set_setup_guard(ci); | ||
976 | memcpy(&req, &hwep->qh.ptr->setup, sizeof(req)); | ||
977 | } while (!hw_test_and_clear_setup_guard(ci)); | ||
978 | |||
979 | type = req.bRequestType; | ||
980 | |||
981 | ci->ep0_dir = (type & USB_DIR_IN) ? TX : RX; | ||
982 | |||
983 | switch (req.bRequest) { | ||
984 | case USB_REQ_CLEAR_FEATURE: | ||
985 | if (type == (USB_DIR_OUT|USB_RECIP_ENDPOINT) && | ||
986 | le16_to_cpu(req.wValue) == | ||
987 | USB_ENDPOINT_HALT) { | ||
988 | if (req.wLength != 0) | ||
989 | break; | ||
990 | num = le16_to_cpu(req.wIndex); | ||
991 | dir = num & USB_ENDPOINT_DIR_MASK; | ||
992 | num &= USB_ENDPOINT_NUMBER_MASK; | ||
993 | if (dir) /* TX */ | ||
994 | num += ci->hw_ep_max / 2; | ||
995 | if (!ci->ci_hw_ep[num].wedge) { | ||
996 | spin_unlock(&ci->lock); | ||
997 | err = usb_ep_clear_halt( | ||
998 | &ci->ci_hw_ep[num].ep); | ||
999 | spin_lock(&ci->lock); | ||
1000 | if (err) | ||
1001 | break; | ||
1002 | } | ||
1003 | err = isr_setup_status_phase(ci); | ||
1004 | } else if (type == (USB_DIR_OUT|USB_RECIP_DEVICE) && | ||
1005 | le16_to_cpu(req.wValue) == | ||
1006 | USB_DEVICE_REMOTE_WAKEUP) { | ||
1007 | if (req.wLength != 0) | ||
1008 | break; | ||
1009 | ci->remote_wakeup = 0; | ||
1010 | err = isr_setup_status_phase(ci); | ||
1011 | } else { | ||
1012 | goto delegate; | ||
1013 | } | ||
1014 | break; | ||
1015 | case USB_REQ_GET_STATUS: | ||
1016 | if (type != (USB_DIR_IN|USB_RECIP_DEVICE) && | ||
1017 | type != (USB_DIR_IN|USB_RECIP_ENDPOINT) && | ||
1018 | type != (USB_DIR_IN|USB_RECIP_INTERFACE)) | ||
1019 | goto delegate; | ||
1020 | if (le16_to_cpu(req.wLength) != 2 || | ||
1021 | le16_to_cpu(req.wValue) != 0) | ||
1022 | break; | ||
1023 | err = isr_get_status_response(ci, &req); | ||
1024 | break; | ||
1025 | case USB_REQ_SET_ADDRESS: | ||
1026 | if (type != (USB_DIR_OUT|USB_RECIP_DEVICE)) | ||
1027 | goto delegate; | ||
1028 | if (le16_to_cpu(req.wLength) != 0 || | ||
1029 | le16_to_cpu(req.wIndex) != 0) | ||
1030 | break; | ||
1031 | ci->address = (u8)le16_to_cpu(req.wValue); | ||
1032 | ci->setaddr = true; | ||
1033 | err = isr_setup_status_phase(ci); | ||
1034 | break; | ||
1035 | case USB_REQ_SET_FEATURE: | ||
1036 | if (type == (USB_DIR_OUT|USB_RECIP_ENDPOINT) && | ||
1037 | le16_to_cpu(req.wValue) == | ||
1038 | USB_ENDPOINT_HALT) { | ||
1039 | if (req.wLength != 0) | ||
1040 | break; | ||
1041 | num = le16_to_cpu(req.wIndex); | ||
1042 | dir = num & USB_ENDPOINT_DIR_MASK; | ||
1043 | num &= USB_ENDPOINT_NUMBER_MASK; | ||
1044 | if (dir) /* TX */ | ||
1045 | num += ci->hw_ep_max / 2; | ||
1046 | |||
1047 | spin_unlock(&ci->lock); | ||
1048 | err = usb_ep_set_halt(&ci->ci_hw_ep[num].ep); | ||
1049 | spin_lock(&ci->lock); | ||
1050 | if (!err) | ||
1051 | isr_setup_status_phase(ci); | ||
1052 | } else if (type == (USB_DIR_OUT|USB_RECIP_DEVICE)) { | ||
1053 | if (req.wLength != 0) | ||
1054 | break; | ||
1055 | switch (le16_to_cpu(req.wValue)) { | ||
1056 | case USB_DEVICE_REMOTE_WAKEUP: | ||
1057 | ci->remote_wakeup = 1; | ||
1058 | err = isr_setup_status_phase(ci); | ||
1059 | break; | ||
1060 | case USB_DEVICE_TEST_MODE: | ||
1061 | tmode = le16_to_cpu(req.wIndex) >> 8; | ||
1062 | switch (tmode) { | ||
1063 | case TEST_J: | ||
1064 | case TEST_K: | ||
1065 | case TEST_SE0_NAK: | ||
1066 | case TEST_PACKET: | ||
1067 | case TEST_FORCE_EN: | ||
1068 | ci->test_mode = tmode; | ||
1069 | err = isr_setup_status_phase( | ||
1070 | ci); | ||
1071 | break; | ||
1072 | default: | ||
1073 | break; | ||
1074 | } | ||
1075 | default: | ||
1076 | goto delegate; | ||
1077 | } | ||
1078 | } else { | ||
1079 | goto delegate; | ||
1080 | } | ||
1081 | break; | ||
1082 | default: | ||
1083 | delegate: | ||
1084 | if (req.wLength == 0) /* no data phase */ | ||
1085 | ci->ep0_dir = TX; | ||
1086 | |||
1087 | spin_unlock(&ci->lock); | ||
1088 | err = ci->driver->setup(&ci->gadget, &req); | ||
1089 | spin_lock(&ci->lock); | ||
1090 | break; | ||
1091 | } | ||
1092 | |||
1093 | if (err < 0) { | ||
1094 | spin_unlock(&ci->lock); | ||
1095 | if (usb_ep_set_halt(&hwep->ep)) | ||
1096 | dev_err(ci->dev, "error: ep_set_halt\n"); | ||
1097 | spin_lock(&ci->lock); | ||
1098 | } | ||
1099 | } | ||
1100 | |||
1101 | /** | ||
965 | * isr_tr_complete_handler: transaction complete interrupt handler | 1102 | * isr_tr_complete_handler: transaction complete interrupt handler |
966 | * @ci: UDC descriptor | 1103 | * @ci: UDC descriptor |
967 | * | 1104 | * |
@@ -972,12 +1109,10 @@ __releases(ci->lock) | |||
972 | __acquires(ci->lock) | 1109 | __acquires(ci->lock) |
973 | { | 1110 | { |
974 | unsigned i; | 1111 | unsigned i; |
975 | u8 tmode = 0; | 1112 | int err; |
976 | 1113 | ||
977 | for (i = 0; i < ci->hw_ep_max; i++) { | 1114 | for (i = 0; i < ci->hw_ep_max; i++) { |
978 | struct ci_hw_ep *hwep = &ci->ci_hw_ep[i]; | 1115 | struct ci_hw_ep *hwep = &ci->ci_hw_ep[i]; |
979 | int type, num, dir, err = -EINVAL; | ||
980 | struct usb_ctrlrequest req; | ||
981 | 1116 | ||
982 | if (hwep->ep.desc == NULL) | 1117 | if (hwep->ep.desc == NULL) |
983 | continue; /* not configured */ | 1118 | continue; /* not configured */ |
@@ -997,148 +1132,10 @@ __acquires(ci->lock) | |||
997 | } | 1132 | } |
998 | } | 1133 | } |
999 | 1134 | ||
1000 | if (hwep->type != USB_ENDPOINT_XFER_CONTROL || | 1135 | /* Only handle setup packet below */ |
1001 | !hw_test_and_clear_setup_status(ci, i)) | 1136 | if (i == 0 && |
1002 | continue; | 1137 | hw_test_and_clear(ci, OP_ENDPTSETUPSTAT, BIT(0))) |
1003 | 1138 | isr_setup_packet_handler(ci); | |
1004 | if (i != 0) { | ||
1005 | dev_warn(ci->dev, "ctrl traffic at endpoint %d\n", i); | ||
1006 | continue; | ||
1007 | } | ||
1008 | |||
1009 | /* | ||
1010 | * Flush data and handshake transactions of previous | ||
1011 | * setup packet. | ||
1012 | */ | ||
1013 | _ep_nuke(ci->ep0out); | ||
1014 | _ep_nuke(ci->ep0in); | ||
1015 | |||
1016 | /* read_setup_packet */ | ||
1017 | do { | ||
1018 | hw_test_and_set_setup_guard(ci); | ||
1019 | memcpy(&req, &hwep->qh.ptr->setup, sizeof(req)); | ||
1020 | } while (!hw_test_and_clear_setup_guard(ci)); | ||
1021 | |||
1022 | type = req.bRequestType; | ||
1023 | |||
1024 | ci->ep0_dir = (type & USB_DIR_IN) ? TX : RX; | ||
1025 | |||
1026 | switch (req.bRequest) { | ||
1027 | case USB_REQ_CLEAR_FEATURE: | ||
1028 | if (type == (USB_DIR_OUT|USB_RECIP_ENDPOINT) && | ||
1029 | le16_to_cpu(req.wValue) == | ||
1030 | USB_ENDPOINT_HALT) { | ||
1031 | if (req.wLength != 0) | ||
1032 | break; | ||
1033 | num = le16_to_cpu(req.wIndex); | ||
1034 | dir = num & USB_ENDPOINT_DIR_MASK; | ||
1035 | num &= USB_ENDPOINT_NUMBER_MASK; | ||
1036 | if (dir) /* TX */ | ||
1037 | num += ci->hw_ep_max/2; | ||
1038 | if (!ci->ci_hw_ep[num].wedge) { | ||
1039 | spin_unlock(&ci->lock); | ||
1040 | err = usb_ep_clear_halt( | ||
1041 | &ci->ci_hw_ep[num].ep); | ||
1042 | spin_lock(&ci->lock); | ||
1043 | if (err) | ||
1044 | break; | ||
1045 | } | ||
1046 | err = isr_setup_status_phase(ci); | ||
1047 | } else if (type == (USB_DIR_OUT|USB_RECIP_DEVICE) && | ||
1048 | le16_to_cpu(req.wValue) == | ||
1049 | USB_DEVICE_REMOTE_WAKEUP) { | ||
1050 | if (req.wLength != 0) | ||
1051 | break; | ||
1052 | ci->remote_wakeup = 0; | ||
1053 | err = isr_setup_status_phase(ci); | ||
1054 | } else { | ||
1055 | goto delegate; | ||
1056 | } | ||
1057 | break; | ||
1058 | case USB_REQ_GET_STATUS: | ||
1059 | if (type != (USB_DIR_IN|USB_RECIP_DEVICE) && | ||
1060 | type != (USB_DIR_IN|USB_RECIP_ENDPOINT) && | ||
1061 | type != (USB_DIR_IN|USB_RECIP_INTERFACE)) | ||
1062 | goto delegate; | ||
1063 | if (le16_to_cpu(req.wLength) != 2 || | ||
1064 | le16_to_cpu(req.wValue) != 0) | ||
1065 | break; | ||
1066 | err = isr_get_status_response(ci, &req); | ||
1067 | break; | ||
1068 | case USB_REQ_SET_ADDRESS: | ||
1069 | if (type != (USB_DIR_OUT|USB_RECIP_DEVICE)) | ||
1070 | goto delegate; | ||
1071 | if (le16_to_cpu(req.wLength) != 0 || | ||
1072 | le16_to_cpu(req.wIndex) != 0) | ||
1073 | break; | ||
1074 | ci->address = (u8)le16_to_cpu(req.wValue); | ||
1075 | ci->setaddr = true; | ||
1076 | err = isr_setup_status_phase(ci); | ||
1077 | break; | ||
1078 | case USB_REQ_SET_FEATURE: | ||
1079 | if (type == (USB_DIR_OUT|USB_RECIP_ENDPOINT) && | ||
1080 | le16_to_cpu(req.wValue) == | ||
1081 | USB_ENDPOINT_HALT) { | ||
1082 | if (req.wLength != 0) | ||
1083 | break; | ||
1084 | num = le16_to_cpu(req.wIndex); | ||
1085 | dir = num & USB_ENDPOINT_DIR_MASK; | ||
1086 | num &= USB_ENDPOINT_NUMBER_MASK; | ||
1087 | if (dir) /* TX */ | ||
1088 | num += ci->hw_ep_max/2; | ||
1089 | |||
1090 | spin_unlock(&ci->lock); | ||
1091 | err = usb_ep_set_halt(&ci->ci_hw_ep[num].ep); | ||
1092 | spin_lock(&ci->lock); | ||
1093 | if (!err) | ||
1094 | isr_setup_status_phase(ci); | ||
1095 | } else if (type == (USB_DIR_OUT|USB_RECIP_DEVICE)) { | ||
1096 | if (req.wLength != 0) | ||
1097 | break; | ||
1098 | switch (le16_to_cpu(req.wValue)) { | ||
1099 | case USB_DEVICE_REMOTE_WAKEUP: | ||
1100 | ci->remote_wakeup = 1; | ||
1101 | err = isr_setup_status_phase(ci); | ||
1102 | break; | ||
1103 | case USB_DEVICE_TEST_MODE: | ||
1104 | tmode = le16_to_cpu(req.wIndex) >> 8; | ||
1105 | switch (tmode) { | ||
1106 | case TEST_J: | ||
1107 | case TEST_K: | ||
1108 | case TEST_SE0_NAK: | ||
1109 | case TEST_PACKET: | ||
1110 | case TEST_FORCE_EN: | ||
1111 | ci->test_mode = tmode; | ||
1112 | err = isr_setup_status_phase( | ||
1113 | ci); | ||
1114 | break; | ||
1115 | default: | ||
1116 | break; | ||
1117 | } | ||
1118 | default: | ||
1119 | goto delegate; | ||
1120 | } | ||
1121 | } else { | ||
1122 | goto delegate; | ||
1123 | } | ||
1124 | break; | ||
1125 | default: | ||
1126 | delegate: | ||
1127 | if (req.wLength == 0) /* no data phase */ | ||
1128 | ci->ep0_dir = TX; | ||
1129 | |||
1130 | spin_unlock(&ci->lock); | ||
1131 | err = ci->driver->setup(&ci->gadget, &req); | ||
1132 | spin_lock(&ci->lock); | ||
1133 | break; | ||
1134 | } | ||
1135 | |||
1136 | if (err < 0) { | ||
1137 | spin_unlock(&ci->lock); | ||
1138 | if (usb_ep_set_halt(&hwep->ep)) | ||
1139 | dev_err(ci->dev, "error: ep_set_halt\n"); | ||
1140 | spin_lock(&ci->lock); | ||
1141 | } | ||
1142 | } | 1139 | } |
1143 | } | 1140 | } |
1144 | 1141 | ||
@@ -1193,6 +1190,11 @@ static int ep_enable(struct usb_ep *ep, | |||
1193 | 1190 | ||
1194 | hwep->qh.ptr->td.next |= cpu_to_le32(TD_TERMINATE); /* needed? */ | 1191 | hwep->qh.ptr->td.next |= cpu_to_le32(TD_TERMINATE); /* needed? */ |
1195 | 1192 | ||
1193 | if (hwep->num != 0 && hwep->type == USB_ENDPOINT_XFER_CONTROL) { | ||
1194 | dev_err(hwep->ci->dev, "Set control xfer at non-ep0\n"); | ||
1195 | retval = -EINVAL; | ||
1196 | } | ||
1197 | |||
1196 | /* | 1198 | /* |
1197 | * Enable endpoints in the HW other than ep0 as ep0 | 1199 | * Enable endpoints in the HW other than ep0 as ep0 |
1198 | * is always enabled | 1200 | * is always enabled |
@@ -1837,12 +1839,6 @@ void ci_hdrc_gadget_destroy(struct ci_hdrc *ci) | |||
1837 | 1839 | ||
1838 | dma_pool_destroy(ci->td_pool); | 1840 | dma_pool_destroy(ci->td_pool); |
1839 | dma_pool_destroy(ci->qh_pool); | 1841 | dma_pool_destroy(ci->qh_pool); |
1840 | |||
1841 | if (ci->transceiver) { | ||
1842 | otg_set_peripheral(ci->transceiver->otg, NULL); | ||
1843 | if (ci->global_phy) | ||
1844 | usb_put_phy(ci->transceiver); | ||
1845 | } | ||
1846 | } | 1842 | } |
1847 | 1843 | ||
1848 | static int udc_id_switch_for_device(struct ci_hdrc *ci) | 1844 | static int udc_id_switch_for_device(struct ci_hdrc *ci) |