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

Merge tag 'phy-for-4.3' of git://git.kernel.org/pub/scm/linux/kernel/git/kishon/linux-phy into usb-next

Kishon writes:

phy: for 4.3

*) Add new NXP USB OTG PHY driver
*) Add vbus/id detection, extcon support and fixes in phy-sun4i-usb
driver
*) Add support to use phy-sun4i-usb driver for sun8i-a23 and sun8i-a33
SoCs
*) Other trivial code cleanups, dropping .owner assignment and constify
phy_ops

Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>

+637 -71
+26
Documentation/devicetree/bindings/phy/phy-lpc18xx-usb-otg.txt
··· 1 + NXP LPC18xx/43xx internal USB OTG PHY binding 2 + --------------------------------------------- 3 + 4 + This file contains documentation for the internal USB OTG PHY found 5 + in NXP LPC18xx and LPC43xx SoCs. 6 + 7 + Required properties: 8 + - compatible : must be "nxp,lpc1850-usb-otg-phy" 9 + - clocks : must be exactly one entry 10 + See: Documentation/devicetree/bindings/clock/clock-bindings.txt 11 + - #phy-cells : must be 0 for this phy 12 + See: Documentation/devicetree/bindings/phy/phy-bindings.txt 13 + 14 + The phy node must be a child of the creg syscon node. 15 + 16 + Example: 17 + creg: syscon@40043000 { 18 + compatible = "nxp,lpc1850-creg", "syscon", "simple-mfd"; 19 + reg = <0x40043000 0x1000>; 20 + 21 + usb0_otg_phy: phy@004 { 22 + compatible = "nxp,lpc1850-usb-otg-phy"; 23 + clocks = <&ccu1 CLK_USB0>; 24 + #phy-cells = <0>; 25 + }; 26 + };
+20 -2
Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt
··· 7 7 * allwinner,sun5i-a13-usb-phy 8 8 * allwinner,sun6i-a31-usb-phy 9 9 * allwinner,sun7i-a20-usb-phy 10 + * allwinner,sun8i-a23-usb-phy 11 + * allwinner,sun8i-a33-usb-phy 10 12 - reg : a list of offset + length pairs 11 13 - reg-names : 12 14 * "phy_ctrl" ··· 19 17 - clock-names : 20 18 * "usb_phy" for sun4i, sun5i or sun7i 21 19 * "usb0_phy", "usb1_phy" and "usb2_phy" for sun6i 20 + * "usb0_phy", "usb1_phy" for sun8i 22 21 - resets : a list of phandle + reset specifier pairs 23 22 - reset-names : 24 23 * "usb0_reset" 25 24 * "usb1_reset" 26 25 * "usb2_reset" for sun4i, sun6i or sun7i 26 + 27 + Optional properties: 28 + - usb0_id_det-gpios : gpio phandle for reading the otg id pin value 29 + - usb0_vbus_det-gpios : gpio phandle for detecting the presence of usb0 vbus 30 + - usb0_vbus_power-supply: power-supply phandle for usb0 vbus presence detect 31 + - usb0_vbus-supply : regulator phandle for controller usb0 vbus 32 + - usb1_vbus-supply : regulator phandle for controller usb1 vbus 33 + - usb2_vbus-supply : regulator phandle for controller usb2 vbus 27 34 28 35 Example: 29 36 usbphy: phy@0x01c13400 { ··· 43 32 reg-names = "phy_ctrl", "pmu1", "pmu2"; 44 33 clocks = <&usb_clk 8>; 45 34 clock-names = "usb_phy"; 46 - resets = <&usb_clk 1>, <&usb_clk 2>; 47 - reset-names = "usb1_reset", "usb2_reset"; 35 + resets = <&usb_clk 0>, <&usb_clk 1>, <&usb_clk 2>; 36 + reset-names = "usb0_reset", "usb1_reset", "usb2_reset"; 37 + pinctrl-names = "default"; 38 + pinctrl-0 = <&usb0_id_detect_pin>, <&usb0_vbus_detect_pin>; 39 + usb0_id_det-gpios = <&pio 7 19 GPIO_ACTIVE_HIGH>; /* PH19 */ 40 + usb0_vbus_det-gpios = <&pio 7 22 GPIO_ACTIVE_HIGH>; /* PH22 */ 41 + usb0_vbus-supply = <&reg_usb0_vbus>; 42 + usb1_vbus-supply = <&reg_usb1_vbus>; 43 + usb2_vbus-supply = <&reg_usb2_vbus>; 48 44 };
+13
drivers/phy/Kconfig
··· 54 54 Support for MIPI CSI-2 and MIPI DSI DPHY found on Samsung S5P 55 55 and EXYNOS SoCs. 56 56 57 + config PHY_LPC18XX_USB_OTG 58 + tristate "NXP LPC18xx/43xx SoC USB OTG PHY driver" 59 + depends on OF && (ARCH_LPC18XX || COMPILE_TEST) 60 + depends on MFD_SYSCON 61 + select GENERIC_PHY 62 + help 63 + Enable this to support NXP LPC18xx/43xx internal USB OTG PHY. 64 + 65 + This driver is need for USB0 support on LPC18xx/43xx and takes 66 + care of enabling and clock setup. 67 + 57 68 config PHY_PXA_28NM_HSIC 58 69 tristate "Marvell USB HSIC 28nm PHY Driver" 59 70 depends on HAS_IOMEM ··· 210 199 tristate "Allwinner sunxi SoC USB PHY driver" 211 200 depends on ARCH_SUNXI && HAS_IOMEM && OF 212 201 depends on RESET_CONTROLLER 202 + depends on EXTCON 203 + depends on POWER_SUPPLY 213 204 select GENERIC_PHY 214 205 help 215 206 Enable this to support the transceiver that is part of Allwinner
+1
drivers/phy/Makefile
··· 10 10 obj-$(CONFIG_BCM_KONA_USB2_PHY) += phy-bcm-kona-usb2.o 11 11 obj-$(CONFIG_PHY_EXYNOS_DP_VIDEO) += phy-exynos-dp-video.o 12 12 obj-$(CONFIG_PHY_EXYNOS_MIPI_VIDEO) += phy-exynos-mipi-video.o 13 + obj-$(CONFIG_PHY_LPC18XX_USB_OTG) += phy-lpc18xx-usb-otg.o 13 14 obj-$(CONFIG_PHY_PXA_28NM_USB2) += phy-pxa-28nm-usb2.o 14 15 obj-$(CONFIG_PHY_PXA_28NM_HSIC) += phy-pxa-28nm-hsic.o 15 16 obj-$(CONFIG_PHY_MVEBU_SATA) += phy-mvebu-sata.o
+1 -2
drivers/phy/phy-armada375-usb2.c
··· 51 51 return 0; 52 52 } 53 53 54 - static struct phy_ops armada375_usb_phy_ops = { 54 + static const struct phy_ops armada375_usb_phy_ops = { 55 55 .init = armada375_usb_phy_init, 56 56 .owner = THIS_MODULE, 57 57 }; ··· 149 149 .driver = { 150 150 .of_match_table = of_usb_cluster_table, 151 151 .name = "armada-375-usb-cluster", 152 - .owner = THIS_MODULE, 153 152 } 154 153 }; 155 154 module_platform_driver(armada375_usb_phy_driver);
+1 -1
drivers/phy/phy-bcm-kona-usb2.c
··· 91 91 return 0; 92 92 } 93 93 94 - static struct phy_ops ops = { 94 + static const struct phy_ops ops = { 95 95 .init = bcm_kona_usb_phy_init, 96 96 .power_on = bcm_kona_usb_phy_power_on, 97 97 .power_off = bcm_kona_usb_phy_power_off,
+1 -1
drivers/phy/phy-berlin-sata.c
··· 176 176 return priv->phys[i]->phy; 177 177 } 178 178 179 - static struct phy_ops phy_berlin_sata_ops = { 179 + static const struct phy_ops phy_berlin_sata_ops = { 180 180 .power_on = phy_berlin_sata_power_on, 181 181 .power_off = phy_berlin_sata_power_off, 182 182 .owner = THIS_MODULE,
+6 -7
drivers/phy/phy-berlin-usb.c
··· 147 147 return 0; 148 148 } 149 149 150 - static struct phy_ops phy_berlin_usb_ops = { 150 + static const struct phy_ops phy_berlin_usb_ops = { 151 151 .power_on = phy_berlin_usb_power_on, 152 152 .owner = THIS_MODULE, 153 153 }; 154 154 155 - static const struct of_device_id phy_berlin_sata_of_match[] = { 155 + static const struct of_device_id phy_berlin_usb_of_match[] = { 156 156 { 157 157 .compatible = "marvell,berlin2-usb-phy", 158 158 .data = &phy_berlin_pll_dividers[0], ··· 163 163 }, 164 164 { }, 165 165 }; 166 - MODULE_DEVICE_TABLE(of, phy_berlin_sata_of_match); 166 + MODULE_DEVICE_TABLE(of, phy_berlin_usb_of_match); 167 167 168 168 static int phy_berlin_usb_probe(struct platform_device *pdev) 169 169 { 170 170 const struct of_device_id *match = 171 - of_match_device(phy_berlin_sata_of_match, &pdev->dev); 171 + of_match_device(phy_berlin_usb_of_match, &pdev->dev); 172 172 struct phy_berlin_usb_priv *priv; 173 173 struct resource *res; 174 174 struct phy *phy; ··· 207 207 .probe = phy_berlin_usb_probe, 208 208 .driver = { 209 209 .name = "phy-berlin-usb", 210 - .owner = THIS_MODULE, 211 - .of_match_table = phy_berlin_sata_of_match, 212 - }, 210 + .of_match_table = phy_berlin_usb_of_match, 211 + }, 213 212 }; 214 213 module_platform_driver(phy_berlin_usb_driver); 215 214
+1 -1
drivers/phy/phy-brcmstb-sata.c
··· 122 122 return 0; 123 123 } 124 124 125 - static struct phy_ops phy_ops_28nm = { 125 + static const struct phy_ops phy_ops_28nm = { 126 126 .init = brcm_sata_phy_init, 127 127 .owner = THIS_MODULE, 128 128 };
+1 -1
drivers/phy/phy-dm816x-usb.c
··· 113 113 return 0; 114 114 } 115 115 116 - static struct phy_ops ops = { 116 + static const struct phy_ops ops = { 117 117 .init = dm816x_usb_phy_init, 118 118 .owner = THIS_MODULE, 119 119 };
+1 -1
drivers/phy/phy-exynos-dp-video.c
··· 48 48 EXYNOS5_PHY_ENABLE, 0); 49 49 } 50 50 51 - static struct phy_ops exynos_dp_video_phy_ops = { 51 + static const struct phy_ops exynos_dp_video_phy_ops = { 52 52 .power_on = exynos_dp_video_phy_power_on, 53 53 .power_off = exynos_dp_video_phy_power_off, 54 54 .owner = THIS_MODULE,
+1 -1
drivers/phy/phy-exynos-mipi-video.c
··· 124 124 return state->phys[args->args[0]].phy; 125 125 } 126 126 127 - static struct phy_ops exynos_mipi_video_phy_ops = { 127 + static const struct phy_ops exynos_mipi_video_phy_ops = { 128 128 .power_on = exynos_mipi_video_phy_power_on, 129 129 .power_off = exynos_mipi_video_phy_power_off, 130 130 .owner = THIS_MODULE,
+1 -1
drivers/phy/phy-exynos5-usbdrd.c
··· 537 537 return phy_drd->phys[args->args[0]].phy; 538 538 } 539 539 540 - static struct phy_ops exynos5_usbdrd_phy_ops = { 540 + static const struct phy_ops exynos5_usbdrd_phy_ops = { 541 541 .init = exynos5_usbdrd_phy_init, 542 542 .exit = exynos5_usbdrd_phy_exit, 543 543 .power_on = exynos5_usbdrd_phy_power_on,
+1 -1
drivers/phy/phy-exynos5250-sata.c
··· 154 154 return ret; 155 155 } 156 156 157 - static struct phy_ops exynos_sata_phy_ops = { 157 + static const struct phy_ops exynos_sata_phy_ops = { 158 158 .init = exynos_sata_phy_init, 159 159 .power_on = exynos_sata_phy_power_on, 160 160 .power_off = exynos_sata_phy_power_off,
+1 -1
drivers/phy/phy-hix5hd2-sata.c
··· 129 129 return 0; 130 130 } 131 131 132 - static struct phy_ops hix5hd2_sata_phy_ops = { 132 + static const struct phy_ops hix5hd2_sata_phy_ops = { 133 133 .init = hix5hd2_sata_phy_init, 134 134 .owner = THIS_MODULE, 135 135 };
+143
drivers/phy/phy-lpc18xx-usb-otg.c
··· 1 + /* 2 + * PHY driver for NXP LPC18xx/43xx internal USB OTG PHY 3 + * 4 + * Copyright (C) 2015 Joachim Eastwood <manabian@gmail.com> 5 + * 6 + * This program is free software; you can redistribute it and/or modify 7 + * it under the terms of the GNU General Public License version 2 as 8 + * published by the Free Software Foundation. 9 + * 10 + */ 11 + 12 + #include <linux/clk.h> 13 + #include <linux/err.h> 14 + #include <linux/mfd/syscon.h> 15 + #include <linux/module.h> 16 + #include <linux/of.h> 17 + #include <linux/phy/phy.h> 18 + #include <linux/platform_device.h> 19 + #include <linux/regmap.h> 20 + 21 + /* USB OTG PHY register offset and bit in CREG */ 22 + #define LPC18XX_CREG_CREG0 0x004 23 + #define LPC18XX_CREG_CREG0_USB0PHY BIT(5) 24 + 25 + struct lpc18xx_usb_otg_phy { 26 + struct phy *phy; 27 + struct clk *clk; 28 + struct regmap *reg; 29 + }; 30 + 31 + static int lpc18xx_usb_otg_phy_init(struct phy *phy) 32 + { 33 + struct lpc18xx_usb_otg_phy *lpc = phy_get_drvdata(phy); 34 + int ret; 35 + 36 + /* The PHY must be clocked at 480 MHz */ 37 + ret = clk_set_rate(lpc->clk, 480000000); 38 + if (ret) 39 + return ret; 40 + 41 + return clk_prepare(lpc->clk); 42 + } 43 + 44 + static int lpc18xx_usb_otg_phy_exit(struct phy *phy) 45 + { 46 + struct lpc18xx_usb_otg_phy *lpc = phy_get_drvdata(phy); 47 + 48 + clk_unprepare(lpc->clk); 49 + 50 + return 0; 51 + } 52 + 53 + static int lpc18xx_usb_otg_phy_power_on(struct phy *phy) 54 + { 55 + struct lpc18xx_usb_otg_phy *lpc = phy_get_drvdata(phy); 56 + int ret; 57 + 58 + ret = clk_enable(lpc->clk); 59 + if (ret) 60 + return ret; 61 + 62 + /* The bit in CREG is cleared to enable the PHY */ 63 + return regmap_update_bits(lpc->reg, LPC18XX_CREG_CREG0, 64 + LPC18XX_CREG_CREG0_USB0PHY, 0); 65 + } 66 + 67 + static int lpc18xx_usb_otg_phy_power_off(struct phy *phy) 68 + { 69 + struct lpc18xx_usb_otg_phy *lpc = phy_get_drvdata(phy); 70 + int ret; 71 + 72 + ret = regmap_update_bits(lpc->reg, LPC18XX_CREG_CREG0, 73 + LPC18XX_CREG_CREG0_USB0PHY, 74 + LPC18XX_CREG_CREG0_USB0PHY); 75 + if (ret) 76 + return ret; 77 + 78 + clk_disable(lpc->clk); 79 + 80 + return 0; 81 + } 82 + 83 + static const struct phy_ops lpc18xx_usb_otg_phy_ops = { 84 + .init = lpc18xx_usb_otg_phy_init, 85 + .exit = lpc18xx_usb_otg_phy_exit, 86 + .power_on = lpc18xx_usb_otg_phy_power_on, 87 + .power_off = lpc18xx_usb_otg_phy_power_off, 88 + .owner = THIS_MODULE, 89 + }; 90 + 91 + static int lpc18xx_usb_otg_phy_probe(struct platform_device *pdev) 92 + { 93 + struct phy_provider *phy_provider; 94 + struct lpc18xx_usb_otg_phy *lpc; 95 + 96 + lpc = devm_kzalloc(&pdev->dev, sizeof(*lpc), GFP_KERNEL); 97 + if (!lpc) 98 + return -ENOMEM; 99 + 100 + lpc->reg = syscon_node_to_regmap(pdev->dev.of_node->parent); 101 + if (IS_ERR(lpc->reg)) { 102 + dev_err(&pdev->dev, "failed to get syscon\n"); 103 + return PTR_ERR(lpc->reg); 104 + } 105 + 106 + lpc->clk = devm_clk_get(&pdev->dev, NULL); 107 + if (IS_ERR(lpc->clk)) { 108 + dev_err(&pdev->dev, "failed to get clock\n"); 109 + return PTR_ERR(lpc->clk); 110 + } 111 + 112 + lpc->phy = devm_phy_create(&pdev->dev, NULL, &lpc18xx_usb_otg_phy_ops); 113 + if (IS_ERR(lpc->phy)) { 114 + dev_err(&pdev->dev, "failed to create PHY\n"); 115 + return PTR_ERR(lpc->phy); 116 + } 117 + 118 + phy_set_drvdata(lpc->phy, lpc); 119 + 120 + phy_provider = devm_of_phy_provider_register(&pdev->dev, 121 + of_phy_simple_xlate); 122 + 123 + return PTR_ERR_OR_ZERO(phy_provider); 124 + } 125 + 126 + static const struct of_device_id lpc18xx_usb_otg_phy_match[] = { 127 + { .compatible = "nxp,lpc1850-usb-otg-phy" }, 128 + { } 129 + }; 130 + MODULE_DEVICE_TABLE(of, lpc18xx_usb_otg_phy_match); 131 + 132 + static struct platform_driver lpc18xx_usb_otg_phy_driver = { 133 + .probe = lpc18xx_usb_otg_phy_probe, 134 + .driver = { 135 + .name = "lpc18xx-usb-otg-phy", 136 + .of_match_table = lpc18xx_usb_otg_phy_match, 137 + }, 138 + }; 139 + module_platform_driver(lpc18xx_usb_otg_phy_driver); 140 + 141 + MODULE_AUTHOR("Joachim Eastwood <manabian@gmail.com>"); 142 + MODULE_DESCRIPTION("NXP LPC18xx/43xx USB OTG PHY driver"); 143 + MODULE_LICENSE("GPL v2");
+1 -2
drivers/phy/phy-miphy28lp.c
··· 1132 1132 return miphy_phy->phy; 1133 1133 } 1134 1134 1135 - static struct phy_ops miphy28lp_ops = { 1135 + static const struct phy_ops miphy28lp_ops = { 1136 1136 .init = miphy28lp_init, 1137 1137 .owner = THIS_MODULE, 1138 1138 }; ··· 1268 1268 .probe = miphy28lp_probe, 1269 1269 .driver = { 1270 1270 .name = "miphy28lp-phy", 1271 - .owner = THIS_MODULE, 1272 1271 .of_match_table = miphy28lp_of_match, 1273 1272 } 1274 1273 };
+1 -1
drivers/phy/phy-miphy365x.c
··· 510 510 return miphy_phy->phy; 511 511 } 512 512 513 - static struct phy_ops miphy365x_ops = { 513 + static const struct phy_ops miphy365x_ops = { 514 514 .init = miphy365x_init, 515 515 .owner = THIS_MODULE, 516 516 };
+1 -1
drivers/phy/phy-mvebu-sata.c
··· 75 75 return 0; 76 76 } 77 77 78 - static struct phy_ops phy_mvebu_sata_ops = { 78 + static const struct phy_ops phy_mvebu_sata_ops = { 79 79 .power_on = phy_mvebu_sata_power_on, 80 80 .power_off = phy_mvebu_sata_power_off, 81 81 .owner = THIS_MODULE,
+1 -1
drivers/phy/phy-omap-usb2.c
··· 137 137 return 0; 138 138 } 139 139 140 - static struct phy_ops ops = { 140 + static const struct phy_ops ops = { 141 141 .init = omap_usb_init, 142 142 .power_on = omap_usb_power_on, 143 143 .power_off = omap_usb_power_off,
+1 -1
drivers/phy/phy-qcom-apq8064-sata.c
··· 204 204 return 0; 205 205 } 206 206 207 - static struct phy_ops qcom_apq8064_sata_phy_ops = { 207 + static const struct phy_ops qcom_apq8064_sata_phy_ops = { 208 208 .init = qcom_apq8064_sata_phy_init, 209 209 .exit = qcom_apq8064_sata_phy_exit, 210 210 .owner = THIS_MODULE,
+1 -1
drivers/phy/phy-qcom-ipq806x-sata.c
··· 126 126 return 0; 127 127 } 128 128 129 - static struct phy_ops qcom_ipq806x_sata_phy_ops = { 129 + static const struct phy_ops qcom_ipq806x_sata_phy_ops = { 130 130 .init = qcom_ipq806x_sata_phy_init, 131 131 .exit = qcom_ipq806x_sata_phy_exit, 132 132 .owner = THIS_MODULE,
+1 -1
drivers/phy/phy-qcom-ufs-i.h
··· 150 150 struct ufs_qcom_phy *ufs_qcom_phy); 151 151 struct phy *ufs_qcom_phy_generic_probe(struct platform_device *pdev, 152 152 struct ufs_qcom_phy *common_cfg, 153 - struct phy_ops *ufs_qcom_phy_gen_ops, 153 + const struct phy_ops *ufs_qcom_phy_gen_ops, 154 154 struct ufs_qcom_phy_specific_ops *phy_spec_ops); 155 155 int ufs_qcom_phy_calibrate(struct ufs_qcom_phy *ufs_qcom_phy, 156 156 struct ufs_qcom_phy_calibration *tbl_A, int tbl_size_A,
+1 -2
drivers/phy/phy-qcom-ufs-qmp-14nm.c
··· 115 115 return err; 116 116 } 117 117 118 - static struct phy_ops ufs_qcom_phy_qmp_14nm_phy_ops = { 118 + static const struct phy_ops ufs_qcom_phy_qmp_14nm_phy_ops = { 119 119 .init = ufs_qcom_phy_qmp_14nm_init, 120 120 .exit = ufs_qcom_phy_exit, 121 121 .power_on = ufs_qcom_phy_power_on, ··· 191 191 .driver = { 192 192 .of_match_table = ufs_qcom_phy_qmp_14nm_of_match, 193 193 .name = "ufs_qcom_phy_qmp_14nm", 194 - .owner = THIS_MODULE, 195 194 }, 196 195 }; 197 196
+1 -2
drivers/phy/phy-qcom-ufs-qmp-20nm.c
··· 171 171 return err; 172 172 } 173 173 174 - static struct phy_ops ufs_qcom_phy_qmp_20nm_phy_ops = { 174 + static const struct phy_ops ufs_qcom_phy_qmp_20nm_phy_ops = { 175 175 .init = ufs_qcom_phy_qmp_20nm_init, 176 176 .exit = ufs_qcom_phy_exit, 177 177 .power_on = ufs_qcom_phy_power_on, ··· 247 247 .driver = { 248 248 .of_match_table = ufs_qcom_phy_qmp_20nm_of_match, 249 249 .name = "ufs_qcom_phy_qmp_20nm", 250 - .owner = THIS_MODULE, 251 250 }, 252 251 }; 253 252
+1 -1
drivers/phy/phy-qcom-ufs.c
··· 77 77 78 78 struct phy *ufs_qcom_phy_generic_probe(struct platform_device *pdev, 79 79 struct ufs_qcom_phy *common_cfg, 80 - struct phy_ops *ufs_qcom_phy_gen_ops, 80 + const struct phy_ops *ufs_qcom_phy_gen_ops, 81 81 struct ufs_qcom_phy_specific_ops *phy_spec_ops) 82 82 { 83 83 int err;
+1 -1
drivers/phy/phy-rcar-gen2.c
··· 184 184 return 0; 185 185 } 186 186 187 - static struct phy_ops rcar_gen2_phy_ops = { 187 + static const struct phy_ops rcar_gen2_phy_ops = { 188 188 .init = rcar_gen2_phy_init, 189 189 .exit = rcar_gen2_phy_exit, 190 190 .power_on = rcar_gen2_phy_power_on,
+1 -2
drivers/phy/phy-rockchip-usb.c
··· 84 84 return 0; 85 85 } 86 86 87 - static struct phy_ops ops = { 87 + static const struct phy_ops ops = { 88 88 .power_on = rockchip_usb_phy_power_on, 89 89 .power_off = rockchip_usb_phy_power_off, 90 90 .owner = THIS_MODULE, ··· 146 146 .probe = rockchip_usb_phy_probe, 147 147 .driver = { 148 148 .name = "rockchip-usb-phy", 149 - .owner = THIS_MODULE, 150 149 .of_match_table = rockchip_usb_phy_dt_ids, 151 150 }, 152 151 };
+1 -1
drivers/phy/phy-samsung-usb2.c
··· 71 71 return 0; 72 72 } 73 73 74 - static struct phy_ops samsung_usb2_phy_ops = { 74 + static const struct phy_ops samsung_usb2_phy_ops = { 75 75 .power_on = samsung_usb2_phy_power_on, 76 76 .power_off = samsung_usb2_phy_power_off, 77 77 .owner = THIS_MODULE,
+1 -1
drivers/phy/phy-spear1310-miphy.c
··· 179 179 }; 180 180 MODULE_DEVICE_TABLE(of, spear1310_miphy_of_match); 181 181 182 - static struct phy_ops spear1310_miphy_ops = { 182 + static const struct phy_ops spear1310_miphy_ops = { 183 183 .init = spear1310_miphy_init, 184 184 .exit = spear1310_miphy_exit, 185 185 .owner = THIS_MODULE,
+1 -1
drivers/phy/phy-spear1340-miphy.c
··· 189 189 }; 190 190 MODULE_DEVICE_TABLE(of, spear1340_miphy_of_match); 191 191 192 - static struct phy_ops spear1340_miphy_ops = { 192 + static const struct phy_ops spear1340_miphy_ops = { 193 193 .init = spear1340_miphy_init, 194 194 .exit = spear1340_miphy_exit, 195 195 .owner = THIS_MODULE,
+1 -1
drivers/phy/phy-stih41x-usb.c
··· 112 112 return 0; 113 113 } 114 114 115 - static struct phy_ops stih41x_usb_phy_ops = { 115 + static const struct phy_ops stih41x_usb_phy_ops = { 116 116 .init = stih41x_usb_phy_init, 117 117 .power_on = stih41x_usb_phy_power_on, 118 118 .power_off = stih41x_usb_phy_power_off,
+398 -27
drivers/phy/phy-sun4i-usb.c
··· 1 1 /* 2 2 * Allwinner sun4i USB phy driver 3 3 * 4 - * Copyright (C) 2014 Hans de Goede <hdegoede@redhat.com> 4 + * Copyright (C) 2014-2015 Hans de Goede <hdegoede@redhat.com> 5 5 * 6 6 * Based on code from 7 7 * Allwinner Technology Co., Ltd. <www.allwinnertech.com> ··· 22 22 */ 23 23 24 24 #include <linux/clk.h> 25 + #include <linux/delay.h> 25 26 #include <linux/err.h> 27 + #include <linux/extcon.h> 26 28 #include <linux/io.h> 29 + #include <linux/interrupt.h> 27 30 #include <linux/kernel.h> 28 31 #include <linux/module.h> 29 32 #include <linux/mutex.h> 30 33 #include <linux/of.h> 31 34 #include <linux/of_address.h> 35 + #include <linux/of_gpio.h> 32 36 #include <linux/phy/phy.h> 33 37 #include <linux/phy/phy-sun4i-usb.h> 34 38 #include <linux/platform_device.h> 39 + #include <linux/power_supply.h> 35 40 #include <linux/regulator/consumer.h> 36 41 #include <linux/reset.h> 42 + #include <linux/workqueue.h> 37 43 38 44 #define REG_ISCR 0x00 39 - #define REG_PHYCTL 0x04 45 + #define REG_PHYCTL_A10 0x04 40 46 #define REG_PHYBIST 0x08 41 47 #define REG_PHYTUNE 0x0c 48 + #define REG_PHYCTL_A33 0x10 42 49 43 50 #define PHYCTL_DATA BIT(7) 44 51 ··· 53 46 #define SUNXI_AHB_INCR4_BURST_EN BIT(9) 54 47 #define SUNXI_AHB_INCRX_ALIGN_EN BIT(8) 55 48 #define SUNXI_ULPI_BYPASS_EN BIT(0) 49 + 50 + /* ISCR, Interface Status and Control bits */ 51 + #define ISCR_ID_PULLUP_EN (1 << 17) 52 + #define ISCR_DPDM_PULLUP_EN (1 << 16) 53 + /* sunxi has the phy id/vbus pins not connected, so we use the force bits */ 54 + #define ISCR_FORCE_ID_MASK (3 << 14) 55 + #define ISCR_FORCE_ID_LOW (2 << 14) 56 + #define ISCR_FORCE_ID_HIGH (3 << 14) 57 + #define ISCR_FORCE_VBUS_MASK (3 << 12) 58 + #define ISCR_FORCE_VBUS_LOW (2 << 12) 59 + #define ISCR_FORCE_VBUS_HIGH (3 << 12) 56 60 57 61 /* Common Control Bits for Both PHYs */ 58 62 #define PHY_PLL_BW 0x03 ··· 81 63 82 64 #define MAX_PHYS 3 83 65 66 + /* 67 + * Note do not raise the debounce time, we must report Vusb high within 100ms 68 + * otherwise we get Vbus errors 69 + */ 70 + #define DEBOUNCE_TIME msecs_to_jiffies(50) 71 + #define POLL_TIME msecs_to_jiffies(250) 72 + 84 73 struct sun4i_usb_phy_data { 85 74 void __iomem *base; 86 75 struct mutex mutex; 87 76 int num_phys; 88 77 u32 disc_thresh; 78 + bool has_a33_phyctl; 89 79 struct sun4i_usb_phy { 90 80 struct phy *phy; 91 81 void __iomem *pmu; 92 82 struct regulator *vbus; 93 83 struct reset_control *reset; 94 84 struct clk *clk; 85 + bool regulator_on; 95 86 int index; 96 87 } phys[MAX_PHYS]; 88 + /* phy0 / otg related variables */ 89 + struct extcon_dev *extcon; 90 + bool phy0_init; 91 + bool phy0_poll; 92 + struct gpio_desc *id_det_gpio; 93 + struct gpio_desc *vbus_det_gpio; 94 + struct power_supply *vbus_power_supply; 95 + struct notifier_block vbus_power_nb; 96 + bool vbus_power_nb_registered; 97 + int id_det_irq; 98 + int vbus_det_irq; 99 + int id_det; 100 + int vbus_det; 101 + struct delayed_work detect; 97 102 }; 98 103 99 104 #define to_sun4i_usb_phy_data(phy) \ 100 105 container_of((phy), struct sun4i_usb_phy_data, phys[(phy)->index]) 106 + 107 + static void sun4i_usb_phy0_update_iscr(struct phy *_phy, u32 clr, u32 set) 108 + { 109 + struct sun4i_usb_phy *phy = phy_get_drvdata(_phy); 110 + struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy); 111 + u32 iscr; 112 + 113 + iscr = readl(data->base + REG_ISCR); 114 + iscr &= ~clr; 115 + iscr |= set; 116 + writel(iscr, data->base + REG_ISCR); 117 + } 118 + 119 + static void sun4i_usb_phy0_set_id_detect(struct phy *phy, u32 val) 120 + { 121 + if (val) 122 + val = ISCR_FORCE_ID_HIGH; 123 + else 124 + val = ISCR_FORCE_ID_LOW; 125 + 126 + sun4i_usb_phy0_update_iscr(phy, ISCR_FORCE_ID_MASK, val); 127 + } 128 + 129 + static void sun4i_usb_phy0_set_vbus_detect(struct phy *phy, u32 val) 130 + { 131 + if (val) 132 + val = ISCR_FORCE_VBUS_HIGH; 133 + else 134 + val = ISCR_FORCE_VBUS_LOW; 135 + 136 + sun4i_usb_phy0_update_iscr(phy, ISCR_FORCE_VBUS_MASK, val); 137 + } 101 138 102 139 static void sun4i_usb_phy_write(struct sun4i_usb_phy *phy, u32 addr, u32 data, 103 140 int len) 104 141 { 105 142 struct sun4i_usb_phy_data *phy_data = to_sun4i_usb_phy_data(phy); 106 143 u32 temp, usbc_bit = BIT(phy->index * 2); 144 + void *phyctl; 107 145 int i; 108 146 109 147 mutex_lock(&phy_data->mutex); 110 148 149 + if (phy_data->has_a33_phyctl) { 150 + phyctl = phy_data->base + REG_PHYCTL_A33; 151 + /* A33 needs us to set phyctl to 0 explicitly */ 152 + writel(0, phyctl); 153 + } else { 154 + phyctl = phy_data->base + REG_PHYCTL_A10; 155 + } 156 + 111 157 for (i = 0; i < len; i++) { 112 - temp = readl(phy_data->base + REG_PHYCTL); 158 + temp = readl(phyctl); 113 159 114 160 /* clear the address portion */ 115 161 temp &= ~(0xff << 8); 116 162 117 163 /* set the address */ 118 164 temp |= ((addr + i) << 8); 119 - writel(temp, phy_data->base + REG_PHYCTL); 165 + writel(temp, phyctl); 120 166 121 167 /* set the data bit and clear usbc bit*/ 122 - temp = readb(phy_data->base + REG_PHYCTL); 168 + temp = readb(phyctl); 123 169 if (data & 0x1) 124 170 temp |= PHYCTL_DATA; 125 171 else 126 172 temp &= ~PHYCTL_DATA; 127 173 temp &= ~usbc_bit; 128 - writeb(temp, phy_data->base + REG_PHYCTL); 174 + writeb(temp, phyctl); 129 175 130 176 /* pulse usbc_bit */ 131 - temp = readb(phy_data->base + REG_PHYCTL); 177 + temp = readb(phyctl); 132 178 temp |= usbc_bit; 133 - writeb(temp, phy_data->base + REG_PHYCTL); 179 + writeb(temp, phyctl); 134 180 135 - temp = readb(phy_data->base + REG_PHYCTL); 181 + temp = readb(phyctl); 136 182 temp &= ~usbc_bit; 137 - writeb(temp, phy_data->base + REG_PHYCTL); 183 + writeb(temp, phyctl); 138 184 139 185 data >>= 1; 140 186 } ··· 253 171 254 172 sun4i_usb_phy_passby(phy, 1); 255 173 174 + if (phy->index == 0) { 175 + data->phy0_init = true; 176 + 177 + /* Enable pull-ups */ 178 + sun4i_usb_phy0_update_iscr(_phy, 0, ISCR_DPDM_PULLUP_EN); 179 + sun4i_usb_phy0_update_iscr(_phy, 0, ISCR_ID_PULLUP_EN); 180 + 181 + if (data->id_det_gpio) { 182 + /* OTG mode, force ISCR and cable state updates */ 183 + data->id_det = -1; 184 + data->vbus_det = -1; 185 + queue_delayed_work(system_wq, &data->detect, 0); 186 + } else { 187 + /* Host only mode */ 188 + sun4i_usb_phy0_set_id_detect(_phy, 0); 189 + sun4i_usb_phy0_set_vbus_detect(_phy, 1); 190 + } 191 + } 192 + 256 193 return 0; 257 194 } 258 195 259 196 static int sun4i_usb_phy_exit(struct phy *_phy) 260 197 { 261 198 struct sun4i_usb_phy *phy = phy_get_drvdata(_phy); 199 + struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy); 200 + 201 + if (phy->index == 0) { 202 + /* Disable pull-ups */ 203 + sun4i_usb_phy0_update_iscr(_phy, ISCR_DPDM_PULLUP_EN, 0); 204 + sun4i_usb_phy0_update_iscr(_phy, ISCR_ID_PULLUP_EN, 0); 205 + data->phy0_init = false; 206 + } 262 207 263 208 sun4i_usb_phy_passby(phy, 0); 264 209 reset_control_assert(phy->reset); ··· 294 185 return 0; 295 186 } 296 187 188 + static int sun4i_usb_phy0_get_vbus_det(struct sun4i_usb_phy_data *data) 189 + { 190 + if (data->vbus_det_gpio) 191 + return gpiod_get_value_cansleep(data->vbus_det_gpio); 192 + 193 + if (data->vbus_power_supply) { 194 + union power_supply_propval val; 195 + int r; 196 + 197 + r = power_supply_get_property(data->vbus_power_supply, 198 + POWER_SUPPLY_PROP_PRESENT, &val); 199 + if (r == 0) 200 + return val.intval; 201 + } 202 + 203 + /* Fallback: report vbus as high */ 204 + return 1; 205 + } 206 + 207 + static bool sun4i_usb_phy0_have_vbus_det(struct sun4i_usb_phy_data *data) 208 + { 209 + return data->vbus_det_gpio || data->vbus_power_supply; 210 + } 211 + 297 212 static int sun4i_usb_phy_power_on(struct phy *_phy) 298 213 { 299 214 struct sun4i_usb_phy *phy = phy_get_drvdata(_phy); 300 - int ret = 0; 215 + struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy); 216 + int ret; 301 217 302 - if (phy->vbus) 303 - ret = regulator_enable(phy->vbus); 218 + if (!phy->vbus || phy->regulator_on) 219 + return 0; 304 220 305 - return ret; 221 + /* For phy0 only turn on Vbus if we don't have an ext. Vbus */ 222 + if (phy->index == 0 && sun4i_usb_phy0_have_vbus_det(data) && 223 + data->vbus_det) 224 + return 0; 225 + 226 + ret = regulator_enable(phy->vbus); 227 + if (ret) 228 + return ret; 229 + 230 + phy->regulator_on = true; 231 + 232 + /* We must report Vbus high within OTG_TIME_A_WAIT_VRISE msec. */ 233 + if (phy->index == 0 && data->vbus_det_gpio && data->phy0_poll) 234 + mod_delayed_work(system_wq, &data->detect, DEBOUNCE_TIME); 235 + 236 + return 0; 306 237 } 307 238 308 239 static int sun4i_usb_phy_power_off(struct phy *_phy) 309 240 { 310 241 struct sun4i_usb_phy *phy = phy_get_drvdata(_phy); 242 + struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy); 311 243 312 - if (phy->vbus) 313 - regulator_disable(phy->vbus); 244 + if (!phy->vbus || !phy->regulator_on) 245 + return 0; 246 + 247 + regulator_disable(phy->vbus); 248 + phy->regulator_on = false; 249 + 250 + /* 251 + * phy0 vbus typically slowly discharges, sometimes this causes the 252 + * Vbus gpio to not trigger an edge irq on Vbus off, so force a rescan. 253 + */ 254 + if (phy->index == 0 && data->vbus_det_gpio && !data->phy0_poll) 255 + mod_delayed_work(system_wq, &data->detect, POLL_TIME); 314 256 315 257 return 0; 316 258 } ··· 374 214 } 375 215 EXPORT_SYMBOL_GPL(sun4i_usb_phy_set_squelch_detect); 376 216 377 - static struct phy_ops sun4i_usb_phy_ops = { 217 + static const struct phy_ops sun4i_usb_phy_ops = { 378 218 .init = sun4i_usb_phy_init, 379 219 .exit = sun4i_usb_phy_exit, 380 220 .power_on = sun4i_usb_phy_power_on, 381 221 .power_off = sun4i_usb_phy_power_off, 382 222 .owner = THIS_MODULE, 383 223 }; 224 + 225 + static void sun4i_usb_phy0_id_vbus_det_scan(struct work_struct *work) 226 + { 227 + struct sun4i_usb_phy_data *data = 228 + container_of(work, struct sun4i_usb_phy_data, detect.work); 229 + struct phy *phy0 = data->phys[0].phy; 230 + int id_det, vbus_det, id_notify = 0, vbus_notify = 0; 231 + 232 + id_det = gpiod_get_value_cansleep(data->id_det_gpio); 233 + vbus_det = sun4i_usb_phy0_get_vbus_det(data); 234 + 235 + mutex_lock(&phy0->mutex); 236 + 237 + if (!data->phy0_init) { 238 + mutex_unlock(&phy0->mutex); 239 + return; 240 + } 241 + 242 + if (id_det != data->id_det) { 243 + /* 244 + * When a host cable (id == 0) gets plugged in on systems 245 + * without vbus detection report vbus low for long enough for 246 + * the musb-ip to end the current device session. 247 + */ 248 + if (!sun4i_usb_phy0_have_vbus_det(data) && id_det == 0) { 249 + sun4i_usb_phy0_set_vbus_detect(phy0, 0); 250 + msleep(200); 251 + sun4i_usb_phy0_set_vbus_detect(phy0, 1); 252 + } 253 + sun4i_usb_phy0_set_id_detect(phy0, id_det); 254 + data->id_det = id_det; 255 + id_notify = 1; 256 + } 257 + 258 + if (vbus_det != data->vbus_det) { 259 + sun4i_usb_phy0_set_vbus_detect(phy0, vbus_det); 260 + data->vbus_det = vbus_det; 261 + vbus_notify = 1; 262 + } 263 + 264 + mutex_unlock(&phy0->mutex); 265 + 266 + if (id_notify) { 267 + extcon_set_cable_state_(data->extcon, EXTCON_USB_HOST, 268 + !id_det); 269 + /* 270 + * When a host cable gets unplugged (id == 1) on systems 271 + * without vbus detection report vbus low for long enough to 272 + * the musb-ip to end the current host session. 273 + */ 274 + if (!sun4i_usb_phy0_have_vbus_det(data) && id_det == 1) { 275 + mutex_lock(&phy0->mutex); 276 + sun4i_usb_phy0_set_vbus_detect(phy0, 0); 277 + msleep(1000); 278 + sun4i_usb_phy0_set_vbus_detect(phy0, 1); 279 + mutex_unlock(&phy0->mutex); 280 + } 281 + } 282 + 283 + if (vbus_notify) 284 + extcon_set_cable_state_(data->extcon, EXTCON_USB, vbus_det); 285 + 286 + if (data->phy0_poll) 287 + queue_delayed_work(system_wq, &data->detect, POLL_TIME); 288 + } 289 + 290 + static irqreturn_t sun4i_usb_phy0_id_vbus_det_irq(int irq, void *dev_id) 291 + { 292 + struct sun4i_usb_phy_data *data = dev_id; 293 + 294 + /* vbus or id changed, let the pins settle and then scan them */ 295 + mod_delayed_work(system_wq, &data->detect, DEBOUNCE_TIME); 296 + 297 + return IRQ_HANDLED; 298 + } 299 + 300 + static int sun4i_usb_phy0_vbus_notify(struct notifier_block *nb, 301 + unsigned long val, void *v) 302 + { 303 + struct sun4i_usb_phy_data *data = 304 + container_of(nb, struct sun4i_usb_phy_data, vbus_power_nb); 305 + struct power_supply *psy = v; 306 + 307 + /* Properties on the vbus_power_supply changed, scan vbus_det */ 308 + if (val == PSY_EVENT_PROP_CHANGED && psy == data->vbus_power_supply) 309 + mod_delayed_work(system_wq, &data->detect, DEBOUNCE_TIME); 310 + 311 + return NOTIFY_OK; 312 + } 384 313 385 314 static struct phy *sun4i_usb_phy_xlate(struct device *dev, 386 315 struct of_phandle_args *args) ··· 482 233 return data->phys[args->args[0]].phy; 483 234 } 484 235 236 + static int sun4i_usb_phy_remove(struct platform_device *pdev) 237 + { 238 + struct device *dev = &pdev->dev; 239 + struct sun4i_usb_phy_data *data = dev_get_drvdata(dev); 240 + 241 + if (data->vbus_power_nb_registered) 242 + power_supply_unreg_notifier(&data->vbus_power_nb); 243 + if (data->id_det_irq >= 0) 244 + devm_free_irq(dev, data->id_det_irq, data); 245 + if (data->vbus_det_irq >= 0) 246 + devm_free_irq(dev, data->vbus_det_irq, data); 247 + 248 + cancel_delayed_work_sync(&data->detect); 249 + 250 + return 0; 251 + } 252 + 253 + static const unsigned int sun4i_usb_phy0_cable[] = { 254 + EXTCON_USB, 255 + EXTCON_USB_HOST, 256 + EXTCON_NONE, 257 + }; 258 + 485 259 static int sun4i_usb_phy_probe(struct platform_device *pdev) 486 260 { 487 261 struct sun4i_usb_phy_data *data; ··· 513 241 struct phy_provider *phy_provider; 514 242 bool dedicated_clocks; 515 243 struct resource *res; 516 - int i; 244 + int i, ret; 517 245 518 246 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 519 247 if (!data) 520 248 return -ENOMEM; 521 249 522 250 mutex_init(&data->mutex); 251 + INIT_DELAYED_WORK(&data->detect, sun4i_usb_phy0_id_vbus_det_scan); 252 + dev_set_drvdata(dev, data); 523 253 524 - if (of_device_is_compatible(np, "allwinner,sun5i-a13-usb-phy")) 254 + if (of_device_is_compatible(np, "allwinner,sun5i-a13-usb-phy") || 255 + of_device_is_compatible(np, "allwinner,sun8i-a23-usb-phy") || 256 + of_device_is_compatible(np, "allwinner,sun8i-a33-usb-phy")) 525 257 data->num_phys = 2; 526 258 else 527 259 data->num_phys = 3; 528 260 529 - if (of_device_is_compatible(np, "allwinner,sun4i-a10-usb-phy") || 530 - of_device_is_compatible(np, "allwinner,sun6i-a31-usb-phy")) 531 - data->disc_thresh = 3; 532 - else 261 + if (of_device_is_compatible(np, "allwinner,sun5i-a13-usb-phy") || 262 + of_device_is_compatible(np, "allwinner,sun7i-a20-usb-phy")) 533 263 data->disc_thresh = 2; 264 + else 265 + data->disc_thresh = 3; 534 266 535 - if (of_device_is_compatible(np, "allwinner,sun6i-a31-usb-phy")) 267 + if (of_device_is_compatible(np, "allwinner,sun6i-a31-usb-phy") || 268 + of_device_is_compatible(np, "allwinner,sun8i-a23-usb-phy") || 269 + of_device_is_compatible(np, "allwinner,sun8i-a33-usb-phy")) 536 270 dedicated_clocks = true; 537 271 else 538 272 dedicated_clocks = false; 273 + 274 + if (of_device_is_compatible(np, "allwinner,sun8i-a33-usb-phy")) 275 + data->has_a33_phyctl = true; 539 276 540 277 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy_ctrl"); 541 278 data->base = devm_ioremap_resource(dev, res); 542 279 if (IS_ERR(data->base)) 543 280 return PTR_ERR(data->base); 281 + 282 + data->id_det_gpio = devm_gpiod_get(dev, "usb0_id_det", GPIOD_IN); 283 + if (IS_ERR(data->id_det_gpio)) { 284 + if (PTR_ERR(data->id_det_gpio) == -EPROBE_DEFER) 285 + return -EPROBE_DEFER; 286 + data->id_det_gpio = NULL; 287 + } 288 + 289 + data->vbus_det_gpio = devm_gpiod_get(dev, "usb0_vbus_det", GPIOD_IN); 290 + if (IS_ERR(data->vbus_det_gpio)) { 291 + if (PTR_ERR(data->vbus_det_gpio) == -EPROBE_DEFER) 292 + return -EPROBE_DEFER; 293 + data->vbus_det_gpio = NULL; 294 + } 295 + 296 + if (of_find_property(np, "usb0_vbus_power-supply", NULL)) { 297 + data->vbus_power_supply = devm_power_supply_get_by_phandle(dev, 298 + "usb0_vbus_power-supply"); 299 + if (IS_ERR(data->vbus_power_supply)) 300 + return PTR_ERR(data->vbus_power_supply); 301 + 302 + if (!data->vbus_power_supply) 303 + return -EPROBE_DEFER; 304 + } 305 + 306 + /* vbus_det without id_det makes no sense, and is not supported */ 307 + if (sun4i_usb_phy0_have_vbus_det(data) && !data->id_det_gpio) { 308 + dev_err(dev, "usb0_id_det missing or invalid\n"); 309 + return -ENODEV; 310 + } 311 + 312 + if (data->id_det_gpio) { 313 + data->extcon = devm_extcon_dev_allocate(dev, 314 + sun4i_usb_phy0_cable); 315 + if (IS_ERR(data->extcon)) 316 + return PTR_ERR(data->extcon); 317 + 318 + ret = devm_extcon_dev_register(dev, data->extcon); 319 + if (ret) { 320 + dev_err(dev, "failed to register extcon: %d\n", ret); 321 + return ret; 322 + } 323 + } 544 324 545 325 for (i = 0; i < data->num_phys; i++) { 546 326 struct sun4i_usb_phy *phy = data->phys + i; ··· 643 319 phy_set_drvdata(phy->phy, &data->phys[i]); 644 320 } 645 321 646 - dev_set_drvdata(dev, data); 647 - phy_provider = devm_of_phy_provider_register(dev, sun4i_usb_phy_xlate); 322 + data->id_det_irq = gpiod_to_irq(data->id_det_gpio); 323 + data->vbus_det_irq = gpiod_to_irq(data->vbus_det_gpio); 324 + if ((data->id_det_gpio && data->id_det_irq < 0) || 325 + (data->vbus_det_gpio && data->vbus_det_irq < 0)) 326 + data->phy0_poll = true; 648 327 649 - return PTR_ERR_OR_ZERO(phy_provider); 328 + if (data->id_det_irq >= 0) { 329 + ret = devm_request_irq(dev, data->id_det_irq, 330 + sun4i_usb_phy0_id_vbus_det_irq, 331 + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, 332 + "usb0-id-det", data); 333 + if (ret) { 334 + dev_err(dev, "Err requesting id-det-irq: %d\n", ret); 335 + return ret; 336 + } 337 + } 338 + 339 + if (data->vbus_det_irq >= 0) { 340 + ret = devm_request_irq(dev, data->vbus_det_irq, 341 + sun4i_usb_phy0_id_vbus_det_irq, 342 + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, 343 + "usb0-vbus-det", data); 344 + if (ret) { 345 + dev_err(dev, "Err requesting vbus-det-irq: %d\n", ret); 346 + data->vbus_det_irq = -1; 347 + sun4i_usb_phy_remove(pdev); /* Stop detect work */ 348 + return ret; 349 + } 350 + } 351 + 352 + if (data->vbus_power_supply) { 353 + data->vbus_power_nb.notifier_call = sun4i_usb_phy0_vbus_notify; 354 + data->vbus_power_nb.priority = 0; 355 + ret = power_supply_reg_notifier(&data->vbus_power_nb); 356 + if (ret) { 357 + sun4i_usb_phy_remove(pdev); /* Stop detect work */ 358 + return ret; 359 + } 360 + data->vbus_power_nb_registered = true; 361 + } 362 + 363 + phy_provider = devm_of_phy_provider_register(dev, sun4i_usb_phy_xlate); 364 + if (IS_ERR(phy_provider)) { 365 + sun4i_usb_phy_remove(pdev); /* Stop detect work */ 366 + return PTR_ERR(phy_provider); 367 + } 368 + 369 + return 0; 650 370 } 651 371 652 372 static const struct of_device_id sun4i_usb_phy_of_match[] = { ··· 698 330 { .compatible = "allwinner,sun5i-a13-usb-phy" }, 699 331 { .compatible = "allwinner,sun6i-a31-usb-phy" }, 700 332 { .compatible = "allwinner,sun7i-a20-usb-phy" }, 333 + { .compatible = "allwinner,sun8i-a23-usb-phy" }, 334 + { .compatible = "allwinner,sun8i-a33-usb-phy" }, 701 335 { }, 702 336 }; 703 337 MODULE_DEVICE_TABLE(of, sun4i_usb_phy_of_match); 704 338 705 339 static struct platform_driver sun4i_usb_phy_driver = { 706 340 .probe = sun4i_usb_phy_probe, 341 + .remove = sun4i_usb_phy_remove, 707 342 .driver = { 708 343 .of_match_table = sun4i_usb_phy_of_match, 709 344 .name = "sun4i-usb-phy",
+1 -1
drivers/phy/phy-sun9i-usb.c
··· 114 114 return 0; 115 115 } 116 116 117 - static struct phy_ops sun9i_usb_phy_ops = { 117 + static const struct phy_ops sun9i_usb_phy_ops = { 118 118 .init = sun9i_usb_phy_init, 119 119 .exit = sun9i_usb_phy_exit, 120 120 .owner = THIS_MODULE,
+1 -1
drivers/phy/phy-ti-pipe3.c
··· 298 298 299 299 return 0; 300 300 } 301 - static struct phy_ops ops = { 301 + static const struct phy_ops ops = { 302 302 .init = ti_pipe3_init, 303 303 .exit = ti_pipe3_exit, 304 304 .power_on = ti_pipe3_power_on,
+1 -1
drivers/phy/phy-tusb1210.c
··· 53 53 return 0; 54 54 } 55 55 56 - static struct phy_ops phy_ops = { 56 + static const struct phy_ops phy_ops = { 57 57 .power_on = tusb1210_power_on, 58 58 .power_off = tusb1210_power_off, 59 59 .owner = THIS_MODULE,
+1 -1
drivers/phy/ulpi_phy.h
··· 5 5 * and it's controller, which is always the parent. 6 6 */ 7 7 static inline struct phy 8 - *ulpi_phy_create(struct ulpi *ulpi, struct phy_ops *ops) 8 + *ulpi_phy_create(struct ulpi *ulpi, const struct phy_ops *ops) 9 9 { 10 10 struct phy *phy; 11 11 int ret;