Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

usb: phy: tegra: Support OTG mode programming

Support programming USB PHY into OTG mode.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
Acked-by: Thierry Reding <treding@nvidia.com>
Link: https://lore.kernel.org/r/20210912181718.1328-5-digetx@gmail.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Dmitry Osipenko and committed by
Greg Kroah-Hartman
c1baf6c5 7557c1bf

+198 -5
+193 -5
drivers/usb/phy/phy-tegra-usb.c
··· 63 63 #define A_VBUS_VLD_WAKEUP_EN BIT(30) 64 64 65 65 #define USB_PHY_VBUS_WAKEUP_ID 0x408 66 + #define ID_INT_EN BIT(0) 67 + #define ID_CHG_DET BIT(1) 68 + #define VBUS_WAKEUP_INT_EN BIT(8) 69 + #define VBUS_WAKEUP_CHG_DET BIT(9) 66 70 #define VBUS_WAKEUP_STS BIT(10) 67 71 #define VBUS_WAKEUP_WAKEUP_EN BIT(30) 68 72 ··· 161 157 #define USB_USBMODE_MASK (3 << 0) 162 158 #define USB_USBMODE_HOST (3 << 0) 163 159 #define USB_USBMODE_DEVICE (2 << 0) 160 + 161 + #define PMC_USB_AO 0xf0 162 + #define VBUS_WAKEUP_PD_P0 BIT(2) 163 + #define ID_PD_P0 BIT(3) 164 164 165 165 static DEFINE_SPINLOCK(utmip_pad_lock); 166 166 static unsigned int utmip_pad_count; ··· 541 533 val &= ~USB_WAKE_ON_RESUME_EN; 542 534 writel_relaxed(val, base + USB_SUSP_CTRL); 543 535 544 - if (phy->mode == USB_DR_MODE_PERIPHERAL) { 536 + if (phy->mode != USB_DR_MODE_HOST) { 545 537 val = readl_relaxed(base + USB_SUSP_CTRL); 546 538 val &= ~(USB_WAKE_ON_CNNT_EN_DEV | USB_WAKE_ON_DISCON_EN_DEV); 547 539 writel_relaxed(val, base + USB_SUSP_CTRL); 548 540 549 541 val = readl_relaxed(base + USB_PHY_VBUS_WAKEUP_ID); 550 542 val &= ~VBUS_WAKEUP_WAKEUP_EN; 543 + val &= ~(ID_CHG_DET | VBUS_WAKEUP_CHG_DET); 551 544 writel_relaxed(val, base + USB_PHY_VBUS_WAKEUP_ID); 552 545 553 546 val = readl_relaxed(base + USB_PHY_VBUS_SENSORS); ··· 696 687 * Ask VBUS sensor to generate wake event once cable is 697 688 * connected. 698 689 */ 699 - if (phy->mode == USB_DR_MODE_PERIPHERAL) { 690 + if (phy->mode != USB_DR_MODE_HOST) { 700 691 val = readl_relaxed(base + USB_PHY_VBUS_WAKEUP_ID); 701 692 val |= VBUS_WAKEUP_WAKEUP_EN; 693 + val &= ~(ID_CHG_DET | VBUS_WAKEUP_CHG_DET); 702 694 writel_relaxed(val, base + USB_PHY_VBUS_WAKEUP_ID); 703 695 704 696 val = readl_relaxed(base + USB_PHY_VBUS_SENSORS); ··· 903 893 if (WARN_ON(!phy->freq)) 904 894 return; 905 895 896 + usb_phy_set_wakeup(u_phy, false); 906 897 tegra_usb_phy_power_off(phy); 907 898 908 899 if (!phy->is_ulpi_phy) ··· 915 904 phy->freq = NULL; 916 905 } 917 906 907 + static irqreturn_t tegra_usb_phy_isr(int irq, void *data) 908 + { 909 + u32 val, int_mask = ID_CHG_DET | VBUS_WAKEUP_CHG_DET; 910 + struct tegra_usb_phy *phy = data; 911 + void __iomem *base = phy->regs; 912 + 913 + /* 914 + * The PHY interrupt also wakes the USB controller driver since 915 + * interrupt is shared. We don't do anything in the PHY driver, 916 + * so just clear the interrupt. 917 + */ 918 + val = readl_relaxed(base + USB_PHY_VBUS_WAKEUP_ID); 919 + writel_relaxed(val, base + USB_PHY_VBUS_WAKEUP_ID); 920 + 921 + return val & int_mask ? IRQ_HANDLED : IRQ_NONE; 922 + } 923 + 918 924 static int tegra_usb_phy_set_wakeup(struct usb_phy *u_phy, bool enable) 919 925 { 920 926 struct tegra_usb_phy *phy = to_tegra_usb_phy(u_phy); 927 + void __iomem *base = phy->regs; 928 + int ret = 0; 929 + u32 val; 930 + 931 + if (phy->wakeup_enabled && phy->mode != USB_DR_MODE_HOST && 932 + phy->irq > 0) { 933 + disable_irq(phy->irq); 934 + 935 + val = readl_relaxed(base + USB_PHY_VBUS_WAKEUP_ID); 936 + val &= ~(ID_INT_EN | VBUS_WAKEUP_INT_EN); 937 + writel_relaxed(val, base + USB_PHY_VBUS_WAKEUP_ID); 938 + 939 + enable_irq(phy->irq); 940 + 941 + free_irq(phy->irq, phy); 942 + 943 + phy->wakeup_enabled = false; 944 + } 945 + 946 + if (enable && phy->mode != USB_DR_MODE_HOST && phy->irq > 0) { 947 + ret = request_irq(phy->irq, tegra_usb_phy_isr, IRQF_SHARED, 948 + dev_name(phy->u_phy.dev), phy); 949 + if (!ret) { 950 + disable_irq(phy->irq); 951 + 952 + /* 953 + * USB clock will be resumed once wake event will be 954 + * generated. The ID-change event requires to have 955 + * interrupts enabled, otherwise it won't be generated. 956 + */ 957 + val = readl_relaxed(base + USB_PHY_VBUS_WAKEUP_ID); 958 + val |= ID_INT_EN | VBUS_WAKEUP_INT_EN; 959 + writel_relaxed(val, base + USB_PHY_VBUS_WAKEUP_ID); 960 + 961 + enable_irq(phy->irq); 962 + } else { 963 + dev_err(phy->u_phy.dev, 964 + "Failed to request interrupt: %d", ret); 965 + enable = false; 966 + } 967 + } 921 968 922 969 phy->wakeup_enabled = enable; 923 970 924 - return 0; 971 + return ret; 925 972 } 926 973 927 974 static int tegra_usb_phy_set_suspend(struct usb_phy *u_phy, int suspend) 928 975 { 929 976 struct tegra_usb_phy *phy = to_tegra_usb_phy(u_phy); 977 + int ret; 930 978 931 979 if (WARN_ON(!phy->freq)) 932 980 return -EINVAL; 933 981 982 + /* 983 + * PHY is sharing IRQ with the CI driver, hence here we either 984 + * disable interrupt for both PHY and CI or for CI only. The 985 + * interrupt needs to be disabled while hardware is reprogrammed 986 + * because interrupt touches the programmed registers, and thus, 987 + * there could be a race condition. 988 + */ 989 + if (phy->irq > 0) 990 + disable_irq(phy->irq); 991 + 934 992 if (suspend) 935 - return tegra_usb_phy_power_off(phy); 993 + ret = tegra_usb_phy_power_off(phy); 936 994 else 937 - return tegra_usb_phy_power_on(phy); 995 + ret = tegra_usb_phy_power_on(phy); 996 + 997 + if (phy->irq > 0) 998 + enable_irq(phy->irq); 999 + 1000 + return ret; 1001 + } 1002 + 1003 + static int tegra_usb_phy_configure_pmc(struct tegra_usb_phy *phy) 1004 + { 1005 + int err, val = 0; 1006 + 1007 + /* older device-trees don't have PMC regmap */ 1008 + if (!phy->pmc_regmap) 1009 + return 0; 1010 + 1011 + /* 1012 + * Tegra20 has a different layout of PMC USB register bits and AO is 1013 + * enabled by default after system reset on Tegra20, so assume nothing 1014 + * to do on Tegra20. 1015 + */ 1016 + if (!phy->soc_config->requires_pmc_ao_power_up) 1017 + return 0; 1018 + 1019 + /* enable VBUS wake-up detector */ 1020 + if (phy->mode != USB_DR_MODE_HOST) 1021 + val |= VBUS_WAKEUP_PD_P0 << phy->instance * 4; 1022 + 1023 + /* enable ID-pin ACC detector for OTG mode switching */ 1024 + if (phy->mode == USB_DR_MODE_OTG) 1025 + val |= ID_PD_P0 << phy->instance * 4; 1026 + 1027 + /* disable detectors to reset them */ 1028 + err = regmap_set_bits(phy->pmc_regmap, PMC_USB_AO, val); 1029 + if (err) { 1030 + dev_err(phy->u_phy.dev, "Failed to disable PMC AO: %d\n", err); 1031 + return err; 1032 + } 1033 + 1034 + usleep_range(10, 100); 1035 + 1036 + /* enable detectors */ 1037 + err = regmap_clear_bits(phy->pmc_regmap, PMC_USB_AO, val); 1038 + if (err) { 1039 + dev_err(phy->u_phy.dev, "Failed to enable PMC AO: %d\n", err); 1040 + return err; 1041 + } 1042 + 1043 + /* detectors starts to work after 10ms */ 1044 + usleep_range(10000, 15000); 1045 + 1046 + return 0; 938 1047 } 939 1048 940 1049 static int tegra_usb_phy_init(struct usb_phy *u_phy) ··· 1097 966 if (err) 1098 967 goto disable_vbus; 1099 968 } 969 + 970 + err = tegra_usb_phy_configure_pmc(phy); 971 + if (err) 972 + goto close_phy; 1100 973 1101 974 err = tegra_usb_phy_power_on(phy); 1102 975 if (err) ··· 1270 1135 return 0; 1271 1136 } 1272 1137 1138 + static void tegra_usb_phy_put_pmc_device(void *dev) 1139 + { 1140 + put_device(dev); 1141 + } 1142 + 1143 + static int tegra_usb_phy_parse_pmc(struct device *dev, 1144 + struct tegra_usb_phy *phy) 1145 + { 1146 + struct platform_device *pmc_pdev; 1147 + struct of_phandle_args args; 1148 + int err; 1149 + 1150 + err = of_parse_phandle_with_fixed_args(dev->of_node, "nvidia,pmc", 1151 + 1, 0, &args); 1152 + if (err) { 1153 + if (err != -ENOENT) 1154 + return err; 1155 + 1156 + dev_warn_once(dev, "nvidia,pmc is missing, please update your device-tree\n"); 1157 + return 0; 1158 + } 1159 + 1160 + pmc_pdev = of_find_device_by_node(args.np); 1161 + of_node_put(args.np); 1162 + if (!pmc_pdev) 1163 + return -ENODEV; 1164 + 1165 + err = devm_add_action_or_reset(dev, tegra_usb_phy_put_pmc_device, 1166 + &pmc_pdev->dev); 1167 + if (err) 1168 + return err; 1169 + 1170 + if (!platform_get_drvdata(pmc_pdev)) 1171 + return -EPROBE_DEFER; 1172 + 1173 + phy->pmc_regmap = dev_get_regmap(&pmc_pdev->dev, "usb_sleepwalk"); 1174 + if (!phy->pmc_regmap) 1175 + return -EINVAL; 1176 + 1177 + phy->instance = args.args[0]; 1178 + 1179 + return 0; 1180 + } 1181 + 1273 1182 static const struct tegra_phy_soc_config tegra20_soc_config = { 1274 1183 .utmi_pll_config_in_car_module = false, 1275 1184 .has_hostpc = false, 1276 1185 .requires_usbmode_setup = false, 1277 1186 .requires_extra_tuning_parameters = false, 1187 + .requires_pmc_ao_power_up = false, 1278 1188 }; 1279 1189 1280 1190 static const struct tegra_phy_soc_config tegra30_soc_config = { ··· 1327 1147 .has_hostpc = true, 1328 1148 .requires_usbmode_setup = true, 1329 1149 .requires_extra_tuning_parameters = true, 1150 + .requires_pmc_ao_power_up = true, 1330 1151 }; 1331 1152 1332 1153 static const struct of_device_id tegra_usb_phy_id_table[] = { ··· 1353 1172 return -ENOMEM; 1354 1173 1355 1174 tegra_phy->soc_config = of_device_get_match_data(&pdev->dev); 1175 + tegra_phy->irq = platform_get_irq_optional(pdev, 0); 1356 1176 1357 1177 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1358 1178 if (!res) { ··· 1394 1212 err = PTR_ERR_OR_ZERO(tegra_phy->pll_u); 1395 1213 if (err) { 1396 1214 dev_err(&pdev->dev, "Failed to get pll_u clock: %d\n", err); 1215 + return err; 1216 + } 1217 + 1218 + err = tegra_usb_phy_parse_pmc(&pdev->dev, tegra_phy); 1219 + if (err) { 1220 + dev_err_probe(&pdev->dev, err, "Failed to get PMC regmap\n"); 1397 1221 return err; 1398 1222 } 1399 1223
+5
include/linux/usb/tegra_usb_phy.h
··· 18 18 19 19 #include <linux/clk.h> 20 20 #include <linux/gpio.h> 21 + #include <linux/regmap.h> 21 22 #include <linux/reset.h> 22 23 #include <linux/usb/otg.h> 23 24 ··· 31 30 * enter host mode 32 31 * requires_extra_tuning_parameters: true if xcvr_hsslew, hssquelch_level 33 32 * and hsdiscon_level should be set for adequate signal quality 33 + * requires_pmc_ao_power_up: true if USB AO is powered down by default 34 34 */ 35 35 36 36 struct tegra_phy_soc_config { ··· 39 37 bool has_hostpc; 40 38 bool requires_usbmode_setup; 41 39 bool requires_extra_tuning_parameters; 40 + bool requires_pmc_ao_power_up; 42 41 }; 43 42 44 43 struct tegra_utmip_config { ··· 65 62 struct tegra_xtal_freq; 66 63 67 64 struct tegra_usb_phy { 65 + int irq; 68 66 int instance; 69 67 const struct tegra_xtal_freq *freq; 70 68 void __iomem *regs; ··· 74 70 struct clk *pll_u; 75 71 struct clk *pad_clk; 76 72 struct regulator *vbus; 73 + struct regmap *pmc_regmap; 77 74 enum usb_dr_mode mode; 78 75 void *config; 79 76 const struct tegra_phy_soc_config *soc_config;