.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | | - * Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved. |
---|
3 | | - * |
---|
4 | | - * This program is free software; you can redistribute it and/or modify it |
---|
5 | | - * under the terms and conditions of the GNU General Public License, |
---|
6 | | - * version 2, as published by the Free Software Foundation. |
---|
7 | | - * |
---|
8 | | - * This program is distributed in the hope it will be useful, but WITHOUT |
---|
9 | | - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
---|
10 | | - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
---|
11 | | - * more details. |
---|
| 3 | + * Copyright (c) 2014-2016, NVIDIA CORPORATION. All rights reserved. |
---|
12 | 4 | */ |
---|
13 | 5 | |
---|
14 | 6 | #include <linux/delay.h> |
---|
.. | .. |
---|
68 | 60 | .data = &tegra210_xusb_padctl_soc, |
---|
69 | 61 | }, |
---|
70 | 62 | #endif |
---|
| 63 | +#if defined(CONFIG_ARCH_TEGRA_186_SOC) |
---|
| 64 | + { |
---|
| 65 | + .compatible = "nvidia,tegra186-xusb-padctl", |
---|
| 66 | + .data = &tegra186_xusb_padctl_soc, |
---|
| 67 | + }, |
---|
| 68 | +#endif |
---|
| 69 | +#if defined(CONFIG_ARCH_TEGRA_194_SOC) |
---|
| 70 | + { |
---|
| 71 | + .compatible = "nvidia,tegra194-xusb-padctl", |
---|
| 72 | + .data = &tegra194_xusb_padctl_soc, |
---|
| 73 | + }, |
---|
| 74 | +#endif |
---|
71 | 75 | { } |
---|
72 | 76 | }; |
---|
73 | 77 | MODULE_DEVICE_TABLE(of, tegra_xusb_padctl_of_match); |
---|
.. | .. |
---|
115 | 119 | |
---|
116 | 120 | err = match_string(lane->soc->funcs, lane->soc->num_funcs, function); |
---|
117 | 121 | if (err < 0) { |
---|
118 | | - dev_err(dev, "invalid function \"%s\" for lane \"%s\"\n", |
---|
119 | | - function, np->name); |
---|
| 122 | + dev_err(dev, "invalid function \"%s\" for lane \"%pOFn\"\n", |
---|
| 123 | + function, np); |
---|
120 | 124 | return err; |
---|
121 | 125 | } |
---|
122 | 126 | |
---|
.. | .. |
---|
313 | 317 | const struct tegra_xusb_lane_soc *soc = lane->soc; |
---|
314 | 318 | u32 value; |
---|
315 | 319 | |
---|
| 320 | + /* skip single function lanes */ |
---|
| 321 | + if (soc->num_funcs < 2) |
---|
| 322 | + return; |
---|
| 323 | + |
---|
316 | 324 | /* choose function */ |
---|
317 | 325 | value = padctl_readl(padctl, soc->offset); |
---|
318 | 326 | value &= ~(soc->mask << soc->shift); |
---|
.. | .. |
---|
499 | 507 | |
---|
500 | 508 | static void tegra_xusb_port_release(struct device *dev) |
---|
501 | 509 | { |
---|
| 510 | + struct tegra_xusb_port *port = to_tegra_xusb_port(dev); |
---|
| 511 | + |
---|
| 512 | + if (port->ops->release) |
---|
| 513 | + port->ops->release(port); |
---|
502 | 514 | } |
---|
503 | 515 | |
---|
504 | 516 | static struct device_type tegra_xusb_port_type = { |
---|
.. | .. |
---|
539 | 551 | |
---|
540 | 552 | static void tegra_xusb_port_unregister(struct tegra_xusb_port *port) |
---|
541 | 553 | { |
---|
| 554 | + if (!IS_ERR_OR_NULL(port->usb_role_sw)) { |
---|
| 555 | + of_platform_depopulate(&port->dev); |
---|
| 556 | + usb_role_switch_unregister(port->usb_role_sw); |
---|
| 557 | + cancel_work_sync(&port->usb_phy_work); |
---|
| 558 | + usb_remove_phy(&port->usb_phy); |
---|
| 559 | + port->usb_phy.dev->driver = NULL; |
---|
| 560 | + } |
---|
| 561 | + |
---|
| 562 | + if (port->ops->remove) |
---|
| 563 | + port->ops->remove(port); |
---|
| 564 | + |
---|
542 | 565 | device_unregister(&port->dev); |
---|
| 566 | +} |
---|
| 567 | + |
---|
| 568 | +static const char *const modes[] = { |
---|
| 569 | + [USB_DR_MODE_UNKNOWN] = "", |
---|
| 570 | + [USB_DR_MODE_HOST] = "host", |
---|
| 571 | + [USB_DR_MODE_PERIPHERAL] = "peripheral", |
---|
| 572 | + [USB_DR_MODE_OTG] = "otg", |
---|
| 573 | +}; |
---|
| 574 | + |
---|
| 575 | +static const char * const usb_roles[] = { |
---|
| 576 | + [USB_ROLE_NONE] = "none", |
---|
| 577 | + [USB_ROLE_HOST] = "host", |
---|
| 578 | + [USB_ROLE_DEVICE] = "device", |
---|
| 579 | +}; |
---|
| 580 | + |
---|
| 581 | +static enum usb_phy_events to_usb_phy_event(enum usb_role role) |
---|
| 582 | +{ |
---|
| 583 | + switch (role) { |
---|
| 584 | + case USB_ROLE_DEVICE: |
---|
| 585 | + return USB_EVENT_VBUS; |
---|
| 586 | + |
---|
| 587 | + case USB_ROLE_HOST: |
---|
| 588 | + return USB_EVENT_ID; |
---|
| 589 | + |
---|
| 590 | + default: |
---|
| 591 | + return USB_EVENT_NONE; |
---|
| 592 | + } |
---|
| 593 | +} |
---|
| 594 | + |
---|
| 595 | +static void tegra_xusb_usb_phy_work(struct work_struct *work) |
---|
| 596 | +{ |
---|
| 597 | + struct tegra_xusb_port *port = container_of(work, |
---|
| 598 | + struct tegra_xusb_port, |
---|
| 599 | + usb_phy_work); |
---|
| 600 | + enum usb_role role = usb_role_switch_get_role(port->usb_role_sw); |
---|
| 601 | + |
---|
| 602 | + usb_phy_set_event(&port->usb_phy, to_usb_phy_event(role)); |
---|
| 603 | + |
---|
| 604 | + dev_dbg(&port->dev, "%s(): calling notifier for role %s\n", __func__, |
---|
| 605 | + usb_roles[role]); |
---|
| 606 | + |
---|
| 607 | + atomic_notifier_call_chain(&port->usb_phy.notifier, 0, &port->usb_phy); |
---|
| 608 | +} |
---|
| 609 | + |
---|
| 610 | +static int tegra_xusb_role_sw_set(struct usb_role_switch *sw, |
---|
| 611 | + enum usb_role role) |
---|
| 612 | +{ |
---|
| 613 | + struct tegra_xusb_port *port = usb_role_switch_get_drvdata(sw); |
---|
| 614 | + |
---|
| 615 | + dev_dbg(&port->dev, "%s(): role %s\n", __func__, usb_roles[role]); |
---|
| 616 | + |
---|
| 617 | + schedule_work(&port->usb_phy_work); |
---|
| 618 | + |
---|
| 619 | + return 0; |
---|
| 620 | +} |
---|
| 621 | + |
---|
| 622 | +static int tegra_xusb_set_peripheral(struct usb_otg *otg, |
---|
| 623 | + struct usb_gadget *gadget) |
---|
| 624 | +{ |
---|
| 625 | + struct tegra_xusb_port *port = container_of(otg->usb_phy, |
---|
| 626 | + struct tegra_xusb_port, |
---|
| 627 | + usb_phy); |
---|
| 628 | + |
---|
| 629 | + if (gadget != NULL) |
---|
| 630 | + schedule_work(&port->usb_phy_work); |
---|
| 631 | + |
---|
| 632 | + return 0; |
---|
| 633 | +} |
---|
| 634 | + |
---|
| 635 | +static int tegra_xusb_set_host(struct usb_otg *otg, struct usb_bus *host) |
---|
| 636 | +{ |
---|
| 637 | + struct tegra_xusb_port *port = container_of(otg->usb_phy, |
---|
| 638 | + struct tegra_xusb_port, |
---|
| 639 | + usb_phy); |
---|
| 640 | + |
---|
| 641 | + if (host != NULL) |
---|
| 642 | + schedule_work(&port->usb_phy_work); |
---|
| 643 | + |
---|
| 644 | + return 0; |
---|
| 645 | +} |
---|
| 646 | + |
---|
| 647 | + |
---|
| 648 | +static int tegra_xusb_setup_usb_role_switch(struct tegra_xusb_port *port) |
---|
| 649 | +{ |
---|
| 650 | + struct tegra_xusb_lane *lane; |
---|
| 651 | + struct usb_role_switch_desc role_sx_desc = { |
---|
| 652 | + .fwnode = dev_fwnode(&port->dev), |
---|
| 653 | + .set = tegra_xusb_role_sw_set, |
---|
| 654 | + }; |
---|
| 655 | + int err = 0; |
---|
| 656 | + |
---|
| 657 | + /* |
---|
| 658 | + * USB role switch driver needs parent driver owner info. This is a |
---|
| 659 | + * suboptimal solution. TODO: Need to revisit this in a follow-up patch |
---|
| 660 | + * where an optimal solution is possible with changes to USB role |
---|
| 661 | + * switch driver. |
---|
| 662 | + */ |
---|
| 663 | + port->dev.driver = devm_kzalloc(&port->dev, |
---|
| 664 | + sizeof(struct device_driver), |
---|
| 665 | + GFP_KERNEL); |
---|
| 666 | + if (!port->dev.driver) |
---|
| 667 | + return -ENOMEM; |
---|
| 668 | + |
---|
| 669 | + port->dev.driver->owner = THIS_MODULE; |
---|
| 670 | + |
---|
| 671 | + port->usb_role_sw = usb_role_switch_register(&port->dev, |
---|
| 672 | + &role_sx_desc); |
---|
| 673 | + if (IS_ERR(port->usb_role_sw)) { |
---|
| 674 | + err = PTR_ERR(port->usb_role_sw); |
---|
| 675 | + dev_err(&port->dev, "failed to register USB role switch: %d", |
---|
| 676 | + err); |
---|
| 677 | + return err; |
---|
| 678 | + } |
---|
| 679 | + |
---|
| 680 | + INIT_WORK(&port->usb_phy_work, tegra_xusb_usb_phy_work); |
---|
| 681 | + usb_role_switch_set_drvdata(port->usb_role_sw, port); |
---|
| 682 | + |
---|
| 683 | + port->usb_phy.otg = devm_kzalloc(&port->dev, sizeof(struct usb_otg), |
---|
| 684 | + GFP_KERNEL); |
---|
| 685 | + if (!port->usb_phy.otg) |
---|
| 686 | + return -ENOMEM; |
---|
| 687 | + |
---|
| 688 | + lane = tegra_xusb_find_lane(port->padctl, "usb2", port->index); |
---|
| 689 | + |
---|
| 690 | + /* |
---|
| 691 | + * Assign phy dev to usb-phy dev. Host/device drivers can use phy |
---|
| 692 | + * reference to retrieve usb-phy details. |
---|
| 693 | + */ |
---|
| 694 | + port->usb_phy.dev = &lane->pad->lanes[port->index]->dev; |
---|
| 695 | + port->usb_phy.dev->driver = port->dev.driver; |
---|
| 696 | + port->usb_phy.otg->usb_phy = &port->usb_phy; |
---|
| 697 | + port->usb_phy.otg->set_peripheral = tegra_xusb_set_peripheral; |
---|
| 698 | + port->usb_phy.otg->set_host = tegra_xusb_set_host; |
---|
| 699 | + |
---|
| 700 | + err = usb_add_phy_dev(&port->usb_phy); |
---|
| 701 | + if (err < 0) { |
---|
| 702 | + dev_err(&port->dev, "Failed to add USB PHY: %d\n", err); |
---|
| 703 | + return err; |
---|
| 704 | + } |
---|
| 705 | + |
---|
| 706 | + /* populate connector entry */ |
---|
| 707 | + of_platform_populate(port->dev.of_node, NULL, NULL, &port->dev); |
---|
| 708 | + |
---|
| 709 | + return err; |
---|
543 | 710 | } |
---|
544 | 711 | |
---|
545 | 712 | static int tegra_xusb_usb2_port_parse_dt(struct tegra_xusb_usb2_port *usb2) |
---|
546 | 713 | { |
---|
547 | 714 | struct tegra_xusb_port *port = &usb2->base; |
---|
548 | 715 | struct device_node *np = port->dev.of_node; |
---|
| 716 | + const char *mode; |
---|
| 717 | + int err; |
---|
549 | 718 | |
---|
550 | 719 | usb2->internal = of_property_read_bool(np, "nvidia,internal"); |
---|
551 | 720 | |
---|
552 | | - usb2->supply = devm_regulator_get(&port->dev, "vbus"); |
---|
| 721 | + if (!of_property_read_string(np, "mode", &mode)) { |
---|
| 722 | + int err = match_string(modes, ARRAY_SIZE(modes), mode); |
---|
| 723 | + if (err < 0) { |
---|
| 724 | + dev_err(&port->dev, "invalid value %s for \"mode\"\n", |
---|
| 725 | + mode); |
---|
| 726 | + usb2->mode = USB_DR_MODE_UNKNOWN; |
---|
| 727 | + } else { |
---|
| 728 | + usb2->mode = err; |
---|
| 729 | + } |
---|
| 730 | + } else { |
---|
| 731 | + usb2->mode = USB_DR_MODE_HOST; |
---|
| 732 | + } |
---|
| 733 | + |
---|
| 734 | + /* usb-role-switch property is mandatory for OTG/Peripheral modes */ |
---|
| 735 | + if (usb2->mode == USB_DR_MODE_PERIPHERAL || |
---|
| 736 | + usb2->mode == USB_DR_MODE_OTG) { |
---|
| 737 | + if (of_property_read_bool(np, "usb-role-switch")) { |
---|
| 738 | + err = tegra_xusb_setup_usb_role_switch(port); |
---|
| 739 | + if (err < 0) |
---|
| 740 | + return err; |
---|
| 741 | + } else { |
---|
| 742 | + dev_err(&port->dev, "usb-role-switch not found for %s mode", |
---|
| 743 | + modes[usb2->mode]); |
---|
| 744 | + return -EINVAL; |
---|
| 745 | + } |
---|
| 746 | + } |
---|
| 747 | + |
---|
| 748 | + usb2->supply = regulator_get(&port->dev, "vbus"); |
---|
553 | 749 | return PTR_ERR_OR_ZERO(usb2->supply); |
---|
554 | 750 | } |
---|
555 | 751 | |
---|
.. | .. |
---|
568 | 764 | if (!np || !of_device_is_available(np)) |
---|
569 | 765 | goto out; |
---|
570 | 766 | |
---|
571 | | - usb2 = devm_kzalloc(padctl->dev, sizeof(*usb2), GFP_KERNEL); |
---|
| 767 | + usb2 = kzalloc(sizeof(*usb2), GFP_KERNEL); |
---|
572 | 768 | if (!usb2) { |
---|
573 | 769 | err = -ENOMEM; |
---|
574 | 770 | goto out; |
---|
.. | .. |
---|
583 | 779 | usb2->base.lane = usb2->base.ops->map(&usb2->base); |
---|
584 | 780 | if (IS_ERR(usb2->base.lane)) { |
---|
585 | 781 | err = PTR_ERR(usb2->base.lane); |
---|
| 782 | + tegra_xusb_port_unregister(&usb2->base); |
---|
586 | 783 | goto out; |
---|
587 | 784 | } |
---|
588 | 785 | |
---|
.. | .. |
---|
597 | 794 | out: |
---|
598 | 795 | of_node_put(np); |
---|
599 | 796 | return err; |
---|
| 797 | +} |
---|
| 798 | + |
---|
| 799 | +void tegra_xusb_usb2_port_release(struct tegra_xusb_port *port) |
---|
| 800 | +{ |
---|
| 801 | + struct tegra_xusb_usb2_port *usb2 = to_usb2_port(port); |
---|
| 802 | + |
---|
| 803 | + kfree(usb2); |
---|
| 804 | +} |
---|
| 805 | + |
---|
| 806 | +void tegra_xusb_usb2_port_remove(struct tegra_xusb_port *port) |
---|
| 807 | +{ |
---|
| 808 | + struct tegra_xusb_usb2_port *usb2 = to_usb2_port(port); |
---|
| 809 | + |
---|
| 810 | + regulator_put(usb2->supply); |
---|
600 | 811 | } |
---|
601 | 812 | |
---|
602 | 813 | static int tegra_xusb_ulpi_port_parse_dt(struct tegra_xusb_ulpi_port *ulpi) |
---|
.. | .. |
---|
620 | 831 | if (!np || !of_device_is_available(np)) |
---|
621 | 832 | goto out; |
---|
622 | 833 | |
---|
623 | | - ulpi = devm_kzalloc(padctl->dev, sizeof(*ulpi), GFP_KERNEL); |
---|
| 834 | + ulpi = kzalloc(sizeof(*ulpi), GFP_KERNEL); |
---|
624 | 835 | if (!ulpi) { |
---|
625 | 836 | err = -ENOMEM; |
---|
626 | 837 | goto out; |
---|
.. | .. |
---|
635 | 846 | ulpi->base.lane = ulpi->base.ops->map(&ulpi->base); |
---|
636 | 847 | if (IS_ERR(ulpi->base.lane)) { |
---|
637 | 848 | err = PTR_ERR(ulpi->base.lane); |
---|
| 849 | + tegra_xusb_port_unregister(&ulpi->base); |
---|
638 | 850 | goto out; |
---|
639 | 851 | } |
---|
640 | 852 | |
---|
.. | .. |
---|
649 | 861 | out: |
---|
650 | 862 | of_node_put(np); |
---|
651 | 863 | return err; |
---|
| 864 | +} |
---|
| 865 | + |
---|
| 866 | +void tegra_xusb_ulpi_port_release(struct tegra_xusb_port *port) |
---|
| 867 | +{ |
---|
| 868 | + struct tegra_xusb_ulpi_port *ulpi = to_ulpi_port(port); |
---|
| 869 | + |
---|
| 870 | + kfree(ulpi); |
---|
652 | 871 | } |
---|
653 | 872 | |
---|
654 | 873 | static int tegra_xusb_hsic_port_parse_dt(struct tegra_xusb_hsic_port *hsic) |
---|
.. | .. |
---|
668 | 887 | if (!np || !of_device_is_available(np)) |
---|
669 | 888 | goto out; |
---|
670 | 889 | |
---|
671 | | - hsic = devm_kzalloc(padctl->dev, sizeof(*hsic), GFP_KERNEL); |
---|
| 890 | + hsic = kzalloc(sizeof(*hsic), GFP_KERNEL); |
---|
672 | 891 | if (!hsic) { |
---|
673 | 892 | err = -ENOMEM; |
---|
674 | 893 | goto out; |
---|
.. | .. |
---|
699 | 918 | return err; |
---|
700 | 919 | } |
---|
701 | 920 | |
---|
| 921 | +void tegra_xusb_hsic_port_release(struct tegra_xusb_port *port) |
---|
| 922 | +{ |
---|
| 923 | + struct tegra_xusb_hsic_port *hsic = to_hsic_port(port); |
---|
| 924 | + |
---|
| 925 | + kfree(hsic); |
---|
| 926 | +} |
---|
| 927 | + |
---|
702 | 928 | static int tegra_xusb_usb3_port_parse_dt(struct tegra_xusb_usb3_port *usb3) |
---|
703 | 929 | { |
---|
704 | 930 | struct tegra_xusb_port *port = &usb3->base; |
---|
705 | 931 | struct device_node *np = port->dev.of_node; |
---|
| 932 | + enum usb_device_speed maximum_speed; |
---|
706 | 933 | u32 value; |
---|
707 | 934 | int err; |
---|
708 | 935 | |
---|
.. | .. |
---|
716 | 943 | |
---|
717 | 944 | usb3->internal = of_property_read_bool(np, "nvidia,internal"); |
---|
718 | 945 | |
---|
719 | | - usb3->supply = devm_regulator_get(&port->dev, "vbus"); |
---|
| 946 | + if (device_property_present(&port->dev, "maximum-speed")) { |
---|
| 947 | + maximum_speed = usb_get_maximum_speed(&port->dev); |
---|
| 948 | + if (maximum_speed == USB_SPEED_SUPER) |
---|
| 949 | + usb3->disable_gen2 = true; |
---|
| 950 | + else if (maximum_speed == USB_SPEED_SUPER_PLUS) |
---|
| 951 | + usb3->disable_gen2 = false; |
---|
| 952 | + else |
---|
| 953 | + return -EINVAL; |
---|
| 954 | + } |
---|
| 955 | + |
---|
| 956 | + usb3->supply = regulator_get(&port->dev, "vbus"); |
---|
720 | 957 | return PTR_ERR_OR_ZERO(usb3->supply); |
---|
721 | 958 | } |
---|
722 | 959 | |
---|
.. | .. |
---|
736 | 973 | if (!np || !of_device_is_available(np)) |
---|
737 | 974 | goto out; |
---|
738 | 975 | |
---|
739 | | - usb3 = devm_kzalloc(padctl->dev, sizeof(*usb3), GFP_KERNEL); |
---|
| 976 | + usb3 = kzalloc(sizeof(*usb3), GFP_KERNEL); |
---|
740 | 977 | if (!usb3) { |
---|
741 | 978 | err = -ENOMEM; |
---|
742 | 979 | goto out; |
---|
.. | .. |
---|
767 | 1004 | return err; |
---|
768 | 1005 | } |
---|
769 | 1006 | |
---|
| 1007 | +void tegra_xusb_usb3_port_release(struct tegra_xusb_port *port) |
---|
| 1008 | +{ |
---|
| 1009 | + struct tegra_xusb_usb3_port *usb3 = to_usb3_port(port); |
---|
| 1010 | + |
---|
| 1011 | + kfree(usb3); |
---|
| 1012 | +} |
---|
| 1013 | + |
---|
| 1014 | +void tegra_xusb_usb3_port_remove(struct tegra_xusb_port *port) |
---|
| 1015 | +{ |
---|
| 1016 | + struct tegra_xusb_usb3_port *usb3 = to_usb3_port(port); |
---|
| 1017 | + |
---|
| 1018 | + regulator_put(usb3->supply); |
---|
| 1019 | +} |
---|
| 1020 | + |
---|
770 | 1021 | static void __tegra_xusb_remove_ports(struct tegra_xusb_padctl *padctl) |
---|
771 | 1022 | { |
---|
772 | 1023 | struct tegra_xusb_port *port, *tmp; |
---|
.. | .. |
---|
777 | 1028 | } |
---|
778 | 1029 | } |
---|
779 | 1030 | |
---|
| 1031 | +static int tegra_xusb_find_unused_usb3_port(struct tegra_xusb_padctl *padctl) |
---|
| 1032 | +{ |
---|
| 1033 | + struct device_node *np; |
---|
| 1034 | + unsigned int i; |
---|
| 1035 | + |
---|
| 1036 | + for (i = 0; i < padctl->soc->ports.usb3.count; i++) { |
---|
| 1037 | + np = tegra_xusb_find_port_node(padctl, "usb3", i); |
---|
| 1038 | + if (!np || !of_device_is_available(np)) |
---|
| 1039 | + return i; |
---|
| 1040 | + } |
---|
| 1041 | + |
---|
| 1042 | + return -ENODEV; |
---|
| 1043 | +} |
---|
| 1044 | + |
---|
| 1045 | +static bool tegra_xusb_port_is_companion(struct tegra_xusb_usb2_port *usb2) |
---|
| 1046 | +{ |
---|
| 1047 | + unsigned int i; |
---|
| 1048 | + struct tegra_xusb_usb3_port *usb3; |
---|
| 1049 | + struct tegra_xusb_padctl *padctl = usb2->base.padctl; |
---|
| 1050 | + |
---|
| 1051 | + for (i = 0; i < padctl->soc->ports.usb3.count; i++) { |
---|
| 1052 | + usb3 = tegra_xusb_find_usb3_port(padctl, i); |
---|
| 1053 | + if (usb3 && usb3->port == usb2->base.index) |
---|
| 1054 | + return true; |
---|
| 1055 | + } |
---|
| 1056 | + |
---|
| 1057 | + return false; |
---|
| 1058 | +} |
---|
| 1059 | + |
---|
| 1060 | +static int tegra_xusb_update_usb3_fake_port(struct tegra_xusb_usb2_port *usb2) |
---|
| 1061 | +{ |
---|
| 1062 | + int fake; |
---|
| 1063 | + |
---|
| 1064 | + /* Disable usb3_port_fake usage by default and assign if needed */ |
---|
| 1065 | + usb2->usb3_port_fake = -1; |
---|
| 1066 | + |
---|
| 1067 | + if ((usb2->mode == USB_DR_MODE_OTG || |
---|
| 1068 | + usb2->mode == USB_DR_MODE_PERIPHERAL) && |
---|
| 1069 | + !tegra_xusb_port_is_companion(usb2)) { |
---|
| 1070 | + fake = tegra_xusb_find_unused_usb3_port(usb2->base.padctl); |
---|
| 1071 | + if (fake < 0) { |
---|
| 1072 | + dev_err(&usb2->base.dev, "no unused USB3 ports available\n"); |
---|
| 1073 | + return -ENODEV; |
---|
| 1074 | + } |
---|
| 1075 | + |
---|
| 1076 | + dev_dbg(&usb2->base.dev, "Found unused usb3 port: %d\n", fake); |
---|
| 1077 | + usb2->usb3_port_fake = fake; |
---|
| 1078 | + } |
---|
| 1079 | + |
---|
| 1080 | + return 0; |
---|
| 1081 | +} |
---|
| 1082 | + |
---|
780 | 1083 | static int tegra_xusb_setup_ports(struct tegra_xusb_padctl *padctl) |
---|
781 | 1084 | { |
---|
782 | 1085 | struct tegra_xusb_port *port; |
---|
| 1086 | + struct tegra_xusb_usb2_port *usb2; |
---|
783 | 1087 | unsigned int i; |
---|
784 | 1088 | int err = 0; |
---|
785 | 1089 | |
---|
.. | .. |
---|
807 | 1111 | err = tegra_xusb_add_usb3_port(padctl, i); |
---|
808 | 1112 | if (err < 0) |
---|
809 | 1113 | goto remove_ports; |
---|
| 1114 | + } |
---|
| 1115 | + |
---|
| 1116 | + if (padctl->soc->need_fake_usb3_port) { |
---|
| 1117 | + for (i = 0; i < padctl->soc->ports.usb2.count; i++) { |
---|
| 1118 | + usb2 = tegra_xusb_find_usb2_port(padctl, i); |
---|
| 1119 | + if (!usb2) |
---|
| 1120 | + continue; |
---|
| 1121 | + |
---|
| 1122 | + err = tegra_xusb_update_usb3_fake_port(usb2); |
---|
| 1123 | + if (err < 0) |
---|
| 1124 | + goto remove_ports; |
---|
| 1125 | + } |
---|
810 | 1126 | } |
---|
811 | 1127 | |
---|
812 | 1128 | list_for_each_entry(port, &padctl->ports, list) { |
---|
.. | .. |
---|
876 | 1192 | goto remove; |
---|
877 | 1193 | } |
---|
878 | 1194 | |
---|
| 1195 | + padctl->supplies = devm_kcalloc(&pdev->dev, padctl->soc->num_supplies, |
---|
| 1196 | + sizeof(*padctl->supplies), GFP_KERNEL); |
---|
| 1197 | + if (!padctl->supplies) { |
---|
| 1198 | + err = -ENOMEM; |
---|
| 1199 | + goto remove; |
---|
| 1200 | + } |
---|
| 1201 | + |
---|
| 1202 | + regulator_bulk_set_supply_names(padctl->supplies, |
---|
| 1203 | + padctl->soc->supply_names, |
---|
| 1204 | + padctl->soc->num_supplies); |
---|
| 1205 | + |
---|
| 1206 | + err = devm_regulator_bulk_get(&pdev->dev, padctl->soc->num_supplies, |
---|
| 1207 | + padctl->supplies); |
---|
| 1208 | + if (err < 0) { |
---|
| 1209 | + dev_err(&pdev->dev, "failed to get regulators: %d\n", err); |
---|
| 1210 | + goto remove; |
---|
| 1211 | + } |
---|
| 1212 | + |
---|
879 | 1213 | err = reset_control_deassert(padctl->rst); |
---|
880 | 1214 | if (err < 0) |
---|
881 | 1215 | goto remove; |
---|
882 | 1216 | |
---|
| 1217 | + err = regulator_bulk_enable(padctl->soc->num_supplies, |
---|
| 1218 | + padctl->supplies); |
---|
| 1219 | + if (err < 0) { |
---|
| 1220 | + dev_err(&pdev->dev, "failed to enable supplies: %d\n", err); |
---|
| 1221 | + goto reset; |
---|
| 1222 | + } |
---|
| 1223 | + |
---|
883 | 1224 | err = tegra_xusb_setup_pads(padctl); |
---|
884 | 1225 | if (err < 0) { |
---|
885 | 1226 | dev_err(&pdev->dev, "failed to setup pads: %d\n", err); |
---|
886 | | - goto reset; |
---|
| 1227 | + goto power_down; |
---|
887 | 1228 | } |
---|
888 | 1229 | |
---|
889 | 1230 | err = tegra_xusb_setup_ports(padctl); |
---|
890 | 1231 | if (err) { |
---|
891 | | - dev_err(&pdev->dev, "failed to setup XUSB ports: %d\n", err); |
---|
| 1232 | + const char *level = KERN_ERR; |
---|
| 1233 | + |
---|
| 1234 | + if (err == -EPROBE_DEFER) |
---|
| 1235 | + level = KERN_DEBUG; |
---|
| 1236 | + |
---|
| 1237 | + dev_printk(level, &pdev->dev, |
---|
| 1238 | + dev_fmt("failed to setup XUSB ports: %d\n"), err); |
---|
892 | 1239 | goto remove_pads; |
---|
893 | 1240 | } |
---|
894 | 1241 | |
---|
.. | .. |
---|
896 | 1243 | |
---|
897 | 1244 | remove_pads: |
---|
898 | 1245 | tegra_xusb_remove_pads(padctl); |
---|
| 1246 | +power_down: |
---|
| 1247 | + regulator_bulk_disable(padctl->soc->num_supplies, padctl->supplies); |
---|
899 | 1248 | reset: |
---|
900 | 1249 | reset_control_assert(padctl->rst); |
---|
901 | 1250 | remove: |
---|
.. | .. |
---|
911 | 1260 | |
---|
912 | 1261 | tegra_xusb_remove_ports(padctl); |
---|
913 | 1262 | tegra_xusb_remove_pads(padctl); |
---|
| 1263 | + |
---|
| 1264 | + err = regulator_bulk_disable(padctl->soc->num_supplies, |
---|
| 1265 | + padctl->supplies); |
---|
| 1266 | + if (err < 0) |
---|
| 1267 | + dev_err(&pdev->dev, "failed to disable supplies: %d\n", err); |
---|
914 | 1268 | |
---|
915 | 1269 | err = reset_control_assert(padctl->rst); |
---|
916 | 1270 | if (err < 0) |
---|
.. | .. |
---|
1002 | 1356 | } |
---|
1003 | 1357 | EXPORT_SYMBOL_GPL(tegra_xusb_padctl_usb3_set_lfps_detect); |
---|
1004 | 1358 | |
---|
| 1359 | +int tegra_xusb_padctl_set_vbus_override(struct tegra_xusb_padctl *padctl, |
---|
| 1360 | + bool val) |
---|
| 1361 | +{ |
---|
| 1362 | + if (padctl->soc->ops->vbus_override) |
---|
| 1363 | + return padctl->soc->ops->vbus_override(padctl, val); |
---|
| 1364 | + |
---|
| 1365 | + return -ENOTSUPP; |
---|
| 1366 | +} |
---|
| 1367 | +EXPORT_SYMBOL_GPL(tegra_xusb_padctl_set_vbus_override); |
---|
| 1368 | + |
---|
| 1369 | +int tegra_phy_xusb_utmi_port_reset(struct phy *phy) |
---|
| 1370 | +{ |
---|
| 1371 | + struct tegra_xusb_lane *lane = phy_get_drvdata(phy); |
---|
| 1372 | + struct tegra_xusb_padctl *padctl = lane->pad->padctl; |
---|
| 1373 | + |
---|
| 1374 | + if (padctl->soc->ops->utmi_port_reset) |
---|
| 1375 | + return padctl->soc->ops->utmi_port_reset(phy); |
---|
| 1376 | + |
---|
| 1377 | + return -ENOTSUPP; |
---|
| 1378 | +} |
---|
| 1379 | +EXPORT_SYMBOL_GPL(tegra_phy_xusb_utmi_port_reset); |
---|
| 1380 | + |
---|
| 1381 | +int tegra_xusb_padctl_get_usb3_companion(struct tegra_xusb_padctl *padctl, |
---|
| 1382 | + unsigned int port) |
---|
| 1383 | +{ |
---|
| 1384 | + struct tegra_xusb_usb2_port *usb2; |
---|
| 1385 | + struct tegra_xusb_usb3_port *usb3; |
---|
| 1386 | + int i; |
---|
| 1387 | + |
---|
| 1388 | + usb2 = tegra_xusb_find_usb2_port(padctl, port); |
---|
| 1389 | + if (!usb2) |
---|
| 1390 | + return -EINVAL; |
---|
| 1391 | + |
---|
| 1392 | + for (i = 0; i < padctl->soc->ports.usb3.count; i++) { |
---|
| 1393 | + usb3 = tegra_xusb_find_usb3_port(padctl, i); |
---|
| 1394 | + if (usb3 && usb3->port == usb2->base.index) |
---|
| 1395 | + return usb3->base.index; |
---|
| 1396 | + } |
---|
| 1397 | + |
---|
| 1398 | + return -ENODEV; |
---|
| 1399 | +} |
---|
| 1400 | +EXPORT_SYMBOL_GPL(tegra_xusb_padctl_get_usb3_companion); |
---|
| 1401 | + |
---|
1005 | 1402 | MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>"); |
---|
1006 | 1403 | MODULE_DESCRIPTION("Tegra XUSB Pad Controller driver"); |
---|
1007 | 1404 | MODULE_LICENSE("GPL v2"); |
---|