diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2015-06-03 01:13:41 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2015-06-03 01:13:41 -0400 |
commit | b3d424e3dcbb5eba572baae30e1052b2fff7b51e (patch) | |
tree | 8055b6dca7b3cda1beffc6f5aee3a7602daef09b | |
parent | f50420223071b6ff4b586308f5c27eec54694a81 (diff) | |
parent | 692fbb89fa0b8028f402e33eb912474e11b5f435 (diff) |
Merge tag 'phy-for-v4.2' of git://git.kernel.org/pub/scm/linux/kernel/git/kishon/linux-phy into usb-next
Kishon writes:
phy: for 4.2 merge window
*) new Broadcom SATA3 PHY driver for Broadcom STB SoCs
*) new phy API to get PHY by index which is used in EHCI and
OHCI controller drivers
*) support specifying supply at port level used for multi-port PHYs
*) sparse warning fixes in miphy PHYs
*) fix pm_runtime issues in twl4030 driver
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
-rw-r--r-- | Documentation/ABI/testing/sysfs-platform-twl4030-usb | 8 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/phy/brcm,brcmstb-sata-phy.txt | 40 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/phy/rcar-gen2-phy.txt | 1 | ||||
-rw-r--r-- | Documentation/phy.txt | 7 | ||||
-rw-r--r-- | drivers/phy/Kconfig | 9 | ||||
-rw-r--r-- | drivers/phy/Makefile | 1 | ||||
-rw-r--r-- | drivers/phy/phy-brcmstb-sata.c | 216 | ||||
-rw-r--r-- | drivers/phy/phy-core.c | 67 | ||||
-rw-r--r-- | drivers/phy/phy-miphy28lp.c | 9 | ||||
-rw-r--r-- | drivers/phy/phy-miphy365x.c | 9 | ||||
-rw-r--r-- | drivers/phy/phy-rcar-gen2.c | 6 | ||||
-rw-r--r-- | drivers/phy/phy-twl4030-usb.c | 34 | ||||
-rw-r--r-- | drivers/usb/host/ehci-platform.c | 69 | ||||
-rw-r--r-- | drivers/usb/host/ohci-platform.c | 69 | ||||
-rw-r--r-- | include/linux/phy/phy.h | 9 |
15 files changed, 415 insertions, 139 deletions
diff --git a/Documentation/ABI/testing/sysfs-platform-twl4030-usb b/Documentation/ABI/testing/sysfs-platform-twl4030-usb new file mode 100644 index 000000000000..512c51be64ae --- /dev/null +++ b/Documentation/ABI/testing/sysfs-platform-twl4030-usb | |||
@@ -0,0 +1,8 @@ | |||
1 | What: /sys/bus/platform/devices/*twl4030-usb/vbus | ||
2 | Description: | ||
3 | Read-only status reporting if VBUS (approx 5V) | ||
4 | is being supplied by the USB bus. | ||
5 | |||
6 | Possible values: "on", "off". | ||
7 | |||
8 | Changes are notified via select/poll. | ||
diff --git a/Documentation/devicetree/bindings/phy/brcm,brcmstb-sata-phy.txt b/Documentation/devicetree/bindings/phy/brcm,brcmstb-sata-phy.txt new file mode 100644 index 000000000000..7f81ef90146a --- /dev/null +++ b/Documentation/devicetree/bindings/phy/brcm,brcmstb-sata-phy.txt | |||
@@ -0,0 +1,40 @@ | |||
1 | * Broadcom SATA3 PHY for STB | ||
2 | |||
3 | Required properties: | ||
4 | - compatible: should be one or more of | ||
5 | "brcm,bcm7445-sata-phy" | ||
6 | "brcm,phy-sata3" | ||
7 | - address-cells: should be 1 | ||
8 | - size-cells: should be 0 | ||
9 | - reg: register range for the PHY PCB interface | ||
10 | - reg-names: should be "phy" | ||
11 | |||
12 | Sub-nodes: | ||
13 | Each port's PHY should be represented as a sub-node. | ||
14 | |||
15 | Sub-nodes required properties: | ||
16 | - reg: the PHY number | ||
17 | - phy-cells: generic PHY binding; must be 0 | ||
18 | Optional: | ||
19 | - brcm,enable-ssc: use spread spectrum clocking (SSC) on this port | ||
20 | |||
21 | |||
22 | Example: | ||
23 | |||
24 | sata-phy@f0458100 { | ||
25 | compatible = "brcm,bcm7445-sata-phy", "brcm,phy-sata3"; | ||
26 | reg = <0xf0458100 0x1e00>, <0xf045804c 0x10>; | ||
27 | reg-names = "phy"; | ||
28 | #address-cells = <1>; | ||
29 | #size-cells = <0>; | ||
30 | |||
31 | sata-phy@0 { | ||
32 | reg = <0>; | ||
33 | #phy-cells = <0>; | ||
34 | }; | ||
35 | |||
36 | sata-phy@1 { | ||
37 | reg = <1>; | ||
38 | #phy-cells = <0>; | ||
39 | }; | ||
40 | }; | ||
diff --git a/Documentation/devicetree/bindings/phy/rcar-gen2-phy.txt b/Documentation/devicetree/bindings/phy/rcar-gen2-phy.txt index 00fc52a034b7..d564ba4f1cf6 100644 --- a/Documentation/devicetree/bindings/phy/rcar-gen2-phy.txt +++ b/Documentation/devicetree/bindings/phy/rcar-gen2-phy.txt | |||
@@ -6,6 +6,7 @@ This file provides information on what the device node for the R-Car generation | |||
6 | Required properties: | 6 | Required properties: |
7 | - compatible: "renesas,usb-phy-r8a7790" if the device is a part of R8A7790 SoC. | 7 | - compatible: "renesas,usb-phy-r8a7790" if the device is a part of R8A7790 SoC. |
8 | "renesas,usb-phy-r8a7791" if the device is a part of R8A7791 SoC. | 8 | "renesas,usb-phy-r8a7791" if the device is a part of R8A7791 SoC. |
9 | "renesas,usb-phy-r8a7794" if the device is a part of R8A7794 SoC. | ||
9 | - reg: offset and length of the register block. | 10 | - reg: offset and length of the register block. |
10 | - #address-cells: number of address cells for the USB channel subnodes, must | 11 | - #address-cells: number of address cells for the USB channel subnodes, must |
11 | be <1>. | 12 | be <1>. |
diff --git a/Documentation/phy.txt b/Documentation/phy.txt index 371361c69a4b..b388c5af9e72 100644 --- a/Documentation/phy.txt +++ b/Documentation/phy.txt | |||
@@ -76,6 +76,8 @@ struct phy *phy_get(struct device *dev, const char *string); | |||
76 | struct phy *phy_optional_get(struct device *dev, const char *string); | 76 | struct phy *phy_optional_get(struct device *dev, const char *string); |
77 | struct phy *devm_phy_get(struct device *dev, const char *string); | 77 | struct phy *devm_phy_get(struct device *dev, const char *string); |
78 | struct phy *devm_phy_optional_get(struct device *dev, const char *string); | 78 | struct phy *devm_phy_optional_get(struct device *dev, const char *string); |
79 | struct phy *devm_of_phy_get_by_index(struct device *dev, struct device_node *np, | ||
80 | int index); | ||
79 | 81 | ||
80 | phy_get, phy_optional_get, devm_phy_get and devm_phy_optional_get can | 82 | phy_get, phy_optional_get, devm_phy_get and devm_phy_optional_get can |
81 | be used to get the PHY. In the case of dt boot, the string arguments | 83 | be used to get the PHY. In the case of dt boot, the string arguments |
@@ -86,7 +88,10 @@ successful PHY get. On driver detach, release function is invoked on | |||
86 | the the devres data and devres data is freed. phy_optional_get and | 88 | the the devres data and devres data is freed. phy_optional_get and |
87 | devm_phy_optional_get should be used when the phy is optional. These | 89 | devm_phy_optional_get should be used when the phy is optional. These |
88 | two functions will never return -ENODEV, but instead returns NULL when | 90 | two functions will never return -ENODEV, but instead returns NULL when |
89 | the phy cannot be found. | 91 | the phy cannot be found.Some generic drivers, such as ehci, may use multiple |
92 | phys and for such drivers referencing phy(s) by name(s) does not make sense. In | ||
93 | this case, devm_of_phy_get_by_index can be used to get a phy reference based on | ||
94 | the index. | ||
90 | 95 | ||
91 | It should be noted that NULL is a valid phy reference. All phy | 96 | It should be noted that NULL is a valid phy reference. All phy |
92 | consumer calls on the NULL phy become NOPs. That is the release calls, | 97 | consumer calls on the NULL phy become NOPs. That is the release calls, |
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index fceac96c2a31..56e1b7585d27 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig | |||
@@ -316,4 +316,13 @@ config PHY_TUSB1210 | |||
316 | help | 316 | help |
317 | Support for TI TUSB1210 USB ULPI PHY. | 317 | Support for TI TUSB1210 USB ULPI PHY. |
318 | 318 | ||
319 | config PHY_BRCMSTB_SATA | ||
320 | tristate "Broadcom STB SATA PHY driver" | ||
321 | depends on ARCH_BRCMSTB | ||
322 | depends on OF | ||
323 | select GENERIC_PHY | ||
324 | help | ||
325 | Enable this to support the SATA3 PHY on 28nm Broadcom STB SoCs. | ||
326 | Likely useful only with CONFIG_SATA_BRCMSTB enabled. | ||
327 | |||
319 | endmenu | 328 | endmenu |
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index 0a2041803135..bc92b427e5ca 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile | |||
@@ -41,3 +41,4 @@ obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs.o | |||
41 | obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs-qmp-20nm.o | 41 | obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs-qmp-20nm.o |
42 | obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs-qmp-14nm.o | 42 | obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs-qmp-14nm.o |
43 | obj-$(CONFIG_PHY_TUSB1210) += phy-tusb1210.o | 43 | obj-$(CONFIG_PHY_TUSB1210) += phy-tusb1210.o |
44 | obj-$(CONFIG_PHY_BRCMSTB_SATA) += phy-brcmstb-sata.o | ||
diff --git a/drivers/phy/phy-brcmstb-sata.c b/drivers/phy/phy-brcmstb-sata.c new file mode 100644 index 000000000000..b7e303d28caf --- /dev/null +++ b/drivers/phy/phy-brcmstb-sata.c | |||
@@ -0,0 +1,216 @@ | |||
1 | /* | ||
2 | * Broadcom SATA3 AHCI Controller PHY Driver | ||
3 | * | ||
4 | * Copyright © 2009-2015 Broadcom Corporation | ||
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 as published by | ||
8 | * the Free Software Foundation; either version 2, or (at your option) | ||
9 | * any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | */ | ||
16 | |||
17 | #include <linux/device.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/interrupt.h> | ||
20 | #include <linux/io.h> | ||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/of.h> | ||
24 | #include <linux/phy/phy.h> | ||
25 | #include <linux/platform_device.h> | ||
26 | |||
27 | #define SATA_MDIO_BANK_OFFSET 0x23c | ||
28 | #define SATA_MDIO_REG_OFFSET(ofs) ((ofs) * 4) | ||
29 | #define SATA_MDIO_REG_SPACE_SIZE 0x1000 | ||
30 | #define SATA_MDIO_REG_LENGTH 0x1f00 | ||
31 | |||
32 | #define MAX_PORTS 2 | ||
33 | |||
34 | /* Register offset between PHYs in PCB space */ | ||
35 | #define SATA_MDIO_REG_SPACE_SIZE 0x1000 | ||
36 | |||
37 | struct brcm_sata_port { | ||
38 | int portnum; | ||
39 | struct phy *phy; | ||
40 | struct brcm_sata_phy *phy_priv; | ||
41 | bool ssc_en; | ||
42 | }; | ||
43 | |||
44 | struct brcm_sata_phy { | ||
45 | struct device *dev; | ||
46 | void __iomem *phy_base; | ||
47 | |||
48 | struct brcm_sata_port phys[MAX_PORTS]; | ||
49 | }; | ||
50 | |||
51 | enum sata_mdio_phy_regs_28nm { | ||
52 | PLL_REG_BANK_0 = 0x50, | ||
53 | PLL_REG_BANK_0_PLLCONTROL_0 = 0x81, | ||
54 | |||
55 | TXPMD_REG_BANK = 0x1a0, | ||
56 | TXPMD_CONTROL1 = 0x81, | ||
57 | TXPMD_CONTROL1_TX_SSC_EN_FRC = BIT(0), | ||
58 | TXPMD_CONTROL1_TX_SSC_EN_FRC_VAL = BIT(1), | ||
59 | TXPMD_TX_FREQ_CTRL_CONTROL1 = 0x82, | ||
60 | TXPMD_TX_FREQ_CTRL_CONTROL2 = 0x83, | ||
61 | TXPMD_TX_FREQ_CTRL_CONTROL2_FMIN_MASK = 0x3ff, | ||
62 | TXPMD_TX_FREQ_CTRL_CONTROL3 = 0x84, | ||
63 | TXPMD_TX_FREQ_CTRL_CONTROL3_FMAX_MASK = 0x3ff, | ||
64 | }; | ||
65 | |||
66 | static inline void __iomem *brcm_sata_phy_base(struct brcm_sata_port *port) | ||
67 | { | ||
68 | struct brcm_sata_phy *priv = port->phy_priv; | ||
69 | |||
70 | return priv->phy_base + (port->portnum * SATA_MDIO_REG_SPACE_SIZE); | ||
71 | } | ||
72 | |||
73 | static void brcm_sata_mdio_wr(void __iomem *addr, u32 bank, u32 ofs, | ||
74 | u32 msk, u32 value) | ||
75 | { | ||
76 | u32 tmp; | ||
77 | |||
78 | writel(bank, addr + SATA_MDIO_BANK_OFFSET); | ||
79 | tmp = readl(addr + SATA_MDIO_REG_OFFSET(ofs)); | ||
80 | tmp = (tmp & msk) | value; | ||
81 | writel(tmp, addr + SATA_MDIO_REG_OFFSET(ofs)); | ||
82 | } | ||
83 | |||
84 | /* These defaults were characterized by H/W group */ | ||
85 | #define FMIN_VAL_DEFAULT 0x3df | ||
86 | #define FMAX_VAL_DEFAULT 0x3df | ||
87 | #define FMAX_VAL_SSC 0x83 | ||
88 | |||
89 | static void brcm_sata_cfg_ssc_28nm(struct brcm_sata_port *port) | ||
90 | { | ||
91 | void __iomem *base = brcm_sata_phy_base(port); | ||
92 | struct brcm_sata_phy *priv = port->phy_priv; | ||
93 | u32 tmp; | ||
94 | |||
95 | /* override the TX spread spectrum setting */ | ||
96 | tmp = TXPMD_CONTROL1_TX_SSC_EN_FRC_VAL | TXPMD_CONTROL1_TX_SSC_EN_FRC; | ||
97 | brcm_sata_mdio_wr(base, TXPMD_REG_BANK, TXPMD_CONTROL1, ~tmp, tmp); | ||
98 | |||
99 | /* set fixed min freq */ | ||
100 | brcm_sata_mdio_wr(base, TXPMD_REG_BANK, TXPMD_TX_FREQ_CTRL_CONTROL2, | ||
101 | ~TXPMD_TX_FREQ_CTRL_CONTROL2_FMIN_MASK, | ||
102 | FMIN_VAL_DEFAULT); | ||
103 | |||
104 | /* set fixed max freq depending on SSC config */ | ||
105 | if (port->ssc_en) { | ||
106 | dev_info(priv->dev, "enabling SSC on port %d\n", port->portnum); | ||
107 | tmp = FMAX_VAL_SSC; | ||
108 | } else { | ||
109 | tmp = FMAX_VAL_DEFAULT; | ||
110 | } | ||
111 | |||
112 | brcm_sata_mdio_wr(base, TXPMD_REG_BANK, TXPMD_TX_FREQ_CTRL_CONTROL3, | ||
113 | ~TXPMD_TX_FREQ_CTRL_CONTROL3_FMAX_MASK, tmp); | ||
114 | } | ||
115 | |||
116 | static int brcm_sata_phy_init(struct phy *phy) | ||
117 | { | ||
118 | struct brcm_sata_port *port = phy_get_drvdata(phy); | ||
119 | |||
120 | brcm_sata_cfg_ssc_28nm(port); | ||
121 | |||
122 | return 0; | ||
123 | } | ||
124 | |||
125 | static struct phy_ops phy_ops_28nm = { | ||
126 | .init = brcm_sata_phy_init, | ||
127 | .owner = THIS_MODULE, | ||
128 | }; | ||
129 | |||
130 | static const struct of_device_id brcm_sata_phy_of_match[] = { | ||
131 | { .compatible = "brcm,bcm7445-sata-phy" }, | ||
132 | {}, | ||
133 | }; | ||
134 | MODULE_DEVICE_TABLE(of, brcm_sata_phy_of_match); | ||
135 | |||
136 | static int brcm_sata_phy_probe(struct platform_device *pdev) | ||
137 | { | ||
138 | struct device *dev = &pdev->dev; | ||
139 | struct device_node *dn = dev->of_node, *child; | ||
140 | struct brcm_sata_phy *priv; | ||
141 | struct resource *res; | ||
142 | struct phy_provider *provider; | ||
143 | int count = 0; | ||
144 | |||
145 | if (of_get_child_count(dn) == 0) | ||
146 | return -ENODEV; | ||
147 | |||
148 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); | ||
149 | if (!priv) | ||
150 | return -ENOMEM; | ||
151 | dev_set_drvdata(dev, priv); | ||
152 | priv->dev = dev; | ||
153 | |||
154 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy"); | ||
155 | priv->phy_base = devm_ioremap_resource(dev, res); | ||
156 | if (IS_ERR(priv->phy_base)) | ||
157 | return PTR_ERR(priv->phy_base); | ||
158 | |||
159 | for_each_available_child_of_node(dn, child) { | ||
160 | unsigned int id; | ||
161 | struct brcm_sata_port *port; | ||
162 | |||
163 | if (of_property_read_u32(child, "reg", &id)) { | ||
164 | dev_err(dev, "missing reg property in node %s\n", | ||
165 | child->name); | ||
166 | return -EINVAL; | ||
167 | } | ||
168 | |||
169 | if (id >= MAX_PORTS) { | ||
170 | dev_err(dev, "invalid reg: %u\n", id); | ||
171 | return -EINVAL; | ||
172 | } | ||
173 | if (priv->phys[id].phy) { | ||
174 | dev_err(dev, "already registered port %u\n", id); | ||
175 | return -EINVAL; | ||
176 | } | ||
177 | |||
178 | port = &priv->phys[id]; | ||
179 | port->portnum = id; | ||
180 | port->phy_priv = priv; | ||
181 | port->phy = devm_phy_create(dev, child, &phy_ops_28nm); | ||
182 | port->ssc_en = of_property_read_bool(child, "brcm,enable-ssc"); | ||
183 | if (IS_ERR(port->phy)) { | ||
184 | dev_err(dev, "failed to create PHY\n"); | ||
185 | return PTR_ERR(port->phy); | ||
186 | } | ||
187 | |||
188 | phy_set_drvdata(port->phy, port); | ||
189 | count++; | ||
190 | } | ||
191 | |||
192 | provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); | ||
193 | if (IS_ERR(provider)) { | ||
194 | dev_err(dev, "could not register PHY provider\n"); | ||
195 | return PTR_ERR(provider); | ||
196 | } | ||
197 | |||
198 | dev_info(dev, "registered %d port(s)\n", count); | ||
199 | |||
200 | return 0; | ||
201 | } | ||
202 | |||
203 | static struct platform_driver brcm_sata_phy_driver = { | ||
204 | .probe = brcm_sata_phy_probe, | ||
205 | .driver = { | ||
206 | .of_match_table = brcm_sata_phy_of_match, | ||
207 | .name = "brcmstb-sata-phy", | ||
208 | } | ||
209 | }; | ||
210 | module_platform_driver(brcm_sata_phy_driver); | ||
211 | |||
212 | MODULE_DESCRIPTION("Broadcom STB SATA PHY driver"); | ||
213 | MODULE_LICENSE("GPL"); | ||
214 | MODULE_AUTHOR("Marc Carino"); | ||
215 | MODULE_AUTHOR("Brian Norris"); | ||
216 | MODULE_ALIAS("platform:phy-brcmstb-sata"); | ||
diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c index 3791838f4bd4..7d535dbb63ee 100644 --- a/drivers/phy/phy-core.c +++ b/drivers/phy/phy-core.c | |||
@@ -367,13 +367,21 @@ static struct phy *_of_phy_get(struct device_node *np, int index) | |||
367 | phy_provider = of_phy_provider_lookup(args.np); | 367 | phy_provider = of_phy_provider_lookup(args.np); |
368 | if (IS_ERR(phy_provider) || !try_module_get(phy_provider->owner)) { | 368 | if (IS_ERR(phy_provider) || !try_module_get(phy_provider->owner)) { |
369 | phy = ERR_PTR(-EPROBE_DEFER); | 369 | phy = ERR_PTR(-EPROBE_DEFER); |
370 | goto err0; | 370 | goto out_unlock; |
371 | } | ||
372 | |||
373 | if (!of_device_is_available(args.np)) { | ||
374 | dev_warn(phy_provider->dev, "Requested PHY is disabled\n"); | ||
375 | phy = ERR_PTR(-ENODEV); | ||
376 | goto out_put_module; | ||
371 | } | 377 | } |
372 | 378 | ||
373 | phy = phy_provider->of_xlate(phy_provider->dev, &args); | 379 | phy = phy_provider->of_xlate(phy_provider->dev, &args); |
380 | |||
381 | out_put_module: | ||
374 | module_put(phy_provider->owner); | 382 | module_put(phy_provider->owner); |
375 | 383 | ||
376 | err0: | 384 | out_unlock: |
377 | mutex_unlock(&phy_provider_mutex); | 385 | mutex_unlock(&phy_provider_mutex); |
378 | of_node_put(args.np); | 386 | of_node_put(args.np); |
379 | 387 | ||
@@ -623,6 +631,38 @@ struct phy *devm_of_phy_get(struct device *dev, struct device_node *np, | |||
623 | EXPORT_SYMBOL_GPL(devm_of_phy_get); | 631 | EXPORT_SYMBOL_GPL(devm_of_phy_get); |
624 | 632 | ||
625 | /** | 633 | /** |
634 | * devm_of_phy_get_by_index() - lookup and obtain a reference to a phy by index. | ||
635 | * @dev: device that requests this phy | ||
636 | * @np: node containing the phy | ||
637 | * @index: index of the phy | ||
638 | * | ||
639 | * Gets the phy using _of_phy_get(), and associates a device with it using | ||
640 | * devres. On driver detach, release function is invoked on the devres data, | ||
641 | * then, devres data is freed. | ||
642 | * | ||
643 | */ | ||
644 | struct phy *devm_of_phy_get_by_index(struct device *dev, struct device_node *np, | ||
645 | int index) | ||
646 | { | ||
647 | struct phy **ptr, *phy; | ||
648 | |||
649 | ptr = devres_alloc(devm_phy_release, sizeof(*ptr), GFP_KERNEL); | ||
650 | if (!ptr) | ||
651 | return ERR_PTR(-ENOMEM); | ||
652 | |||
653 | phy = _of_phy_get(np, index); | ||
654 | if (!IS_ERR(phy)) { | ||
655 | *ptr = phy; | ||
656 | devres_add(dev, ptr); | ||
657 | } else { | ||
658 | devres_free(ptr); | ||
659 | } | ||
660 | |||
661 | return phy; | ||
662 | } | ||
663 | EXPORT_SYMBOL_GPL(devm_of_phy_get_by_index); | ||
664 | |||
665 | /** | ||
626 | * phy_create() - create a new phy | 666 | * phy_create() - create a new phy |
627 | * @dev: device that is creating the new phy | 667 | * @dev: device that is creating the new phy |
628 | * @node: device node of the phy | 668 | * @node: device node of the phy |
@@ -651,16 +691,6 @@ struct phy *phy_create(struct device *dev, struct device_node *node, | |||
651 | goto free_phy; | 691 | goto free_phy; |
652 | } | 692 | } |
653 | 693 | ||
654 | /* phy-supply */ | ||
655 | phy->pwr = regulator_get_optional(dev, "phy"); | ||
656 | if (IS_ERR(phy->pwr)) { | ||
657 | if (PTR_ERR(phy->pwr) == -EPROBE_DEFER) { | ||
658 | ret = -EPROBE_DEFER; | ||
659 | goto free_ida; | ||
660 | } | ||
661 | phy->pwr = NULL; | ||
662 | } | ||
663 | |||
664 | device_initialize(&phy->dev); | 694 | device_initialize(&phy->dev); |
665 | mutex_init(&phy->mutex); | 695 | mutex_init(&phy->mutex); |
666 | 696 | ||
@@ -674,6 +704,16 @@ struct phy *phy_create(struct device *dev, struct device_node *node, | |||
674 | if (ret) | 704 | if (ret) |
675 | goto put_dev; | 705 | goto put_dev; |
676 | 706 | ||
707 | /* phy-supply */ | ||
708 | phy->pwr = regulator_get_optional(&phy->dev, "phy"); | ||
709 | if (IS_ERR(phy->pwr)) { | ||
710 | ret = PTR_ERR(phy->pwr); | ||
711 | if (ret == -EPROBE_DEFER) | ||
712 | goto put_dev; | ||
713 | |||
714 | phy->pwr = NULL; | ||
715 | } | ||
716 | |||
677 | ret = device_add(&phy->dev); | 717 | ret = device_add(&phy->dev); |
678 | if (ret) | 718 | if (ret) |
679 | goto put_dev; | 719 | goto put_dev; |
@@ -689,9 +729,6 @@ put_dev: | |||
689 | put_device(&phy->dev); /* calls phy_release() which frees resources */ | 729 | put_device(&phy->dev); /* calls phy_release() which frees resources */ |
690 | return ERR_PTR(ret); | 730 | return ERR_PTR(ret); |
691 | 731 | ||
692 | free_ida: | ||
693 | ida_simple_remove(&phy_ida, phy->id); | ||
694 | |||
695 | free_phy: | 732 | free_phy: |
696 | kfree(phy); | 733 | kfree(phy); |
697 | return ERR_PTR(ret); | 734 | return ERR_PTR(ret); |
diff --git a/drivers/phy/phy-miphy28lp.c b/drivers/phy/phy-miphy28lp.c index c4cc11dcb2a2..5e257ef7ac05 100644 --- a/drivers/phy/phy-miphy28lp.c +++ b/drivers/phy/phy-miphy28lp.c | |||
@@ -367,7 +367,7 @@ static struct miphy28lp_pll_gen pcie_pll_gen[] = { | |||
367 | 367 | ||
368 | static inline void miphy28lp_set_reset(struct miphy28lp_phy *miphy_phy) | 368 | static inline void miphy28lp_set_reset(struct miphy28lp_phy *miphy_phy) |
369 | { | 369 | { |
370 | void *base = miphy_phy->base; | 370 | void __iomem *base = miphy_phy->base; |
371 | u8 val; | 371 | u8 val; |
372 | 372 | ||
373 | /* Putting Macro in reset */ | 373 | /* Putting Macro in reset */ |
@@ -391,7 +391,7 @@ static inline void miphy28lp_set_reset(struct miphy28lp_phy *miphy_phy) | |||
391 | static inline void miphy28lp_pll_calibration(struct miphy28lp_phy *miphy_phy, | 391 | static inline void miphy28lp_pll_calibration(struct miphy28lp_phy *miphy_phy, |
392 | struct pll_ratio *pll_ratio) | 392 | struct pll_ratio *pll_ratio) |
393 | { | 393 | { |
394 | void *base = miphy_phy->base; | 394 | void __iomem *base = miphy_phy->base; |
395 | u8 val; | 395 | u8 val; |
396 | 396 | ||
397 | /* Applying PLL Settings */ | 397 | /* Applying PLL Settings */ |
@@ -1107,11 +1107,6 @@ static struct phy *miphy28lp_xlate(struct device *dev, | |||
1107 | struct device_node *phynode = args->np; | 1107 | struct device_node *phynode = args->np; |
1108 | int ret, index = 0; | 1108 | int ret, index = 0; |
1109 | 1109 | ||
1110 | if (!of_device_is_available(phynode)) { | ||
1111 | dev_warn(dev, "Requested PHY is disabled\n"); | ||
1112 | return ERR_PTR(-ENODEV); | ||
1113 | } | ||
1114 | |||
1115 | if (args->args_count != 1) { | 1110 | if (args->args_count != 1) { |
1116 | dev_err(dev, "Invalid number of cells in 'phy' property\n"); | 1111 | dev_err(dev, "Invalid number of cells in 'phy' property\n"); |
1117 | return ERR_PTR(-EINVAL); | 1112 | return ERR_PTR(-EINVAL); |
diff --git a/drivers/phy/phy-miphy365x.c b/drivers/phy/phy-miphy365x.c index 019c2d75344e..0ff354d6e183 100644 --- a/drivers/phy/phy-miphy365x.c +++ b/drivers/phy/phy-miphy365x.c | |||
@@ -441,8 +441,8 @@ static int miphy365x_init(struct phy *phy) | |||
441 | return ret; | 441 | return ret; |
442 | } | 442 | } |
443 | 443 | ||
444 | int miphy365x_get_addr(struct device *dev, struct miphy365x_phy *miphy_phy, | 444 | static int miphy365x_get_addr(struct device *dev, |
445 | int index) | 445 | struct miphy365x_phy *miphy_phy, int index) |
446 | { | 446 | { |
447 | struct device_node *phynode = miphy_phy->phy->dev.of_node; | 447 | struct device_node *phynode = miphy_phy->phy->dev.of_node; |
448 | const char *name; | 448 | const char *name; |
@@ -476,11 +476,6 @@ static struct phy *miphy365x_xlate(struct device *dev, | |||
476 | struct device_node *phynode = args->np; | 476 | struct device_node *phynode = args->np; |
477 | int ret, index; | 477 | int ret, index; |
478 | 478 | ||
479 | if (!of_device_is_available(phynode)) { | ||
480 | dev_warn(dev, "Requested PHY is disabled\n"); | ||
481 | return ERR_PTR(-ENODEV); | ||
482 | } | ||
483 | |||
484 | if (args->args_count != 1) { | 479 | if (args->args_count != 1) { |
485 | dev_err(dev, "Invalid number of cells in 'phy' property\n"); | 480 | dev_err(dev, "Invalid number of cells in 'phy' property\n"); |
486 | return ERR_PTR(-EINVAL); | 481 | return ERR_PTR(-EINVAL); |
diff --git a/drivers/phy/phy-rcar-gen2.c b/drivers/phy/phy-rcar-gen2.c index 778276aba3aa..0050301dce7a 100644 --- a/drivers/phy/phy-rcar-gen2.c +++ b/drivers/phy/phy-rcar-gen2.c | |||
@@ -195,6 +195,7 @@ static struct phy_ops rcar_gen2_phy_ops = { | |||
195 | static const struct of_device_id rcar_gen2_phy_match_table[] = { | 195 | static const struct of_device_id rcar_gen2_phy_match_table[] = { |
196 | { .compatible = "renesas,usb-phy-r8a7790" }, | 196 | { .compatible = "renesas,usb-phy-r8a7790" }, |
197 | { .compatible = "renesas,usb-phy-r8a7791" }, | 197 | { .compatible = "renesas,usb-phy-r8a7791" }, |
198 | { .compatible = "renesas,usb-phy-r8a7794" }, | ||
198 | { } | 199 | { } |
199 | }; | 200 | }; |
200 | MODULE_DEVICE_TABLE(of, rcar_gen2_phy_match_table); | 201 | MODULE_DEVICE_TABLE(of, rcar_gen2_phy_match_table); |
@@ -206,11 +207,6 @@ static struct phy *rcar_gen2_phy_xlate(struct device *dev, | |||
206 | struct device_node *np = args->np; | 207 | struct device_node *np = args->np; |
207 | int i; | 208 | int i; |
208 | 209 | ||
209 | if (!of_device_is_available(np)) { | ||
210 | dev_warn(dev, "Requested PHY is disabled\n"); | ||
211 | return ERR_PTR(-ENODEV); | ||
212 | } | ||
213 | |||
214 | drv = dev_get_drvdata(dev); | 210 | drv = dev_get_drvdata(dev); |
215 | if (!drv) | 211 | if (!drv) |
216 | return ERR_PTR(-EINVAL); | 212 | return ERR_PTR(-EINVAL); |
diff --git a/drivers/phy/phy-twl4030-usb.c b/drivers/phy/phy-twl4030-usb.c index bc42d6a8939f..3a707dd14238 100644 --- a/drivers/phy/phy-twl4030-usb.c +++ b/drivers/phy/phy-twl4030-usb.c | |||
@@ -144,6 +144,16 @@ | |||
144 | #define PMBR1 0x0D | 144 | #define PMBR1 0x0D |
145 | #define GPIO_USB_4PIN_ULPI_2430C (3 << 0) | 145 | #define GPIO_USB_4PIN_ULPI_2430C (3 << 0) |
146 | 146 | ||
147 | /* | ||
148 | * If VBUS is valid or ID is ground, then we know a | ||
149 | * cable is present and we need to be runtime-enabled | ||
150 | */ | ||
151 | static inline bool cable_present(enum omap_musb_vbus_id_status stat) | ||
152 | { | ||
153 | return stat == OMAP_MUSB_VBUS_VALID || | ||
154 | stat == OMAP_MUSB_ID_GROUND; | ||
155 | } | ||
156 | |||
147 | struct twl4030_usb { | 157 | struct twl4030_usb { |
148 | struct usb_phy phy; | 158 | struct usb_phy phy; |
149 | struct device *dev; | 159 | struct device *dev; |
@@ -386,8 +396,6 @@ static int twl4030_usb_runtime_suspend(struct device *dev) | |||
386 | struct twl4030_usb *twl = dev_get_drvdata(dev); | 396 | struct twl4030_usb *twl = dev_get_drvdata(dev); |
387 | 397 | ||
388 | dev_dbg(twl->dev, "%s\n", __func__); | 398 | dev_dbg(twl->dev, "%s\n", __func__); |
389 | if (pm_runtime_suspended(dev)) | ||
390 | return 0; | ||
391 | 399 | ||
392 | __twl4030_phy_power(twl, 0); | 400 | __twl4030_phy_power(twl, 0); |
393 | regulator_disable(twl->usb1v5); | 401 | regulator_disable(twl->usb1v5); |
@@ -403,8 +411,6 @@ static int twl4030_usb_runtime_resume(struct device *dev) | |||
403 | int res; | 411 | int res; |
404 | 412 | ||
405 | dev_dbg(twl->dev, "%s\n", __func__); | 413 | dev_dbg(twl->dev, "%s\n", __func__); |
406 | if (pm_runtime_active(dev)) | ||
407 | return 0; | ||
408 | 414 | ||
409 | res = regulator_enable(twl->usb3v1); | 415 | res = regulator_enable(twl->usb3v1); |
410 | if (res) | 416 | if (res) |
@@ -536,8 +542,10 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl) | |||
536 | 542 | ||
537 | mutex_lock(&twl->lock); | 543 | mutex_lock(&twl->lock); |
538 | if (status >= 0 && status != twl->linkstat) { | 544 | if (status >= 0 && status != twl->linkstat) { |
545 | status_changed = | ||
546 | cable_present(twl->linkstat) != | ||
547 | cable_present(status); | ||
539 | twl->linkstat = status; | 548 | twl->linkstat = status; |
540 | status_changed = true; | ||
541 | } | 549 | } |
542 | mutex_unlock(&twl->lock); | 550 | mutex_unlock(&twl->lock); |
543 | 551 | ||
@@ -553,15 +561,11 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl) | |||
553 | * USB_LINK_VBUS state. musb_hdrc won't care until it | 561 | * USB_LINK_VBUS state. musb_hdrc won't care until it |
554 | * starts to handle softconnect right. | 562 | * starts to handle softconnect right. |
555 | */ | 563 | */ |
556 | if ((status == OMAP_MUSB_VBUS_VALID) || | 564 | if (cable_present(status)) { |
557 | (status == OMAP_MUSB_ID_GROUND)) { | 565 | pm_runtime_get_sync(twl->dev); |
558 | if (pm_runtime_suspended(twl->dev)) | ||
559 | pm_runtime_get_sync(twl->dev); | ||
560 | } else { | 566 | } else { |
561 | if (pm_runtime_active(twl->dev)) { | 567 | pm_runtime_mark_last_busy(twl->dev); |
562 | pm_runtime_mark_last_busy(twl->dev); | 568 | pm_runtime_put_autosuspend(twl->dev); |
563 | pm_runtime_put_autosuspend(twl->dev); | ||
564 | } | ||
565 | } | 569 | } |
566 | omap_musb_mailbox(status); | 570 | omap_musb_mailbox(status); |
567 | } | 571 | } |
@@ -711,7 +715,6 @@ static int twl4030_usb_probe(struct platform_device *pdev) | |||
711 | pm_runtime_use_autosuspend(&pdev->dev); | 715 | pm_runtime_use_autosuspend(&pdev->dev); |
712 | pm_runtime_set_autosuspend_delay(&pdev->dev, 2000); | 716 | pm_runtime_set_autosuspend_delay(&pdev->dev, 2000); |
713 | pm_runtime_enable(&pdev->dev); | 717 | pm_runtime_enable(&pdev->dev); |
714 | pm_runtime_get_sync(&pdev->dev); | ||
715 | 718 | ||
716 | /* Our job is to use irqs and status from the power module | 719 | /* Our job is to use irqs and status from the power module |
717 | * to keep the transceiver disabled when nothing's connected. | 720 | * to keep the transceiver disabled when nothing's connected. |
@@ -767,6 +770,9 @@ static int twl4030_usb_remove(struct platform_device *pdev) | |||
767 | 770 | ||
768 | /* disable complete OTG block */ | 771 | /* disable complete OTG block */ |
769 | twl4030_usb_clear_bits(twl, POWER_CTRL, POWER_CTRL_OTG_ENAB); | 772 | twl4030_usb_clear_bits(twl, POWER_CTRL, POWER_CTRL_OTG_ENAB); |
773 | |||
774 | if (cable_present(twl->linkstat)) | ||
775 | pm_runtime_put_noidle(twl->dev); | ||
770 | pm_runtime_mark_last_busy(twl->dev); | 776 | pm_runtime_mark_last_busy(twl->dev); |
771 | pm_runtime_put(twl->dev); | 777 | pm_runtime_put(twl->dev); |
772 | 778 | ||
diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c index ba07f16b13e0..2593def13cea 100644 --- a/drivers/usb/host/ehci-platform.c +++ b/drivers/usb/host/ehci-platform.c | |||
@@ -88,15 +88,13 @@ static int ehci_platform_power_on(struct platform_device *dev) | |||
88 | } | 88 | } |
89 | 89 | ||
90 | for (phy_num = 0; phy_num < priv->num_phys; phy_num++) { | 90 | for (phy_num = 0; phy_num < priv->num_phys; phy_num++) { |
91 | if (priv->phys[phy_num]) { | 91 | ret = phy_init(priv->phys[phy_num]); |
92 | ret = phy_init(priv->phys[phy_num]); | 92 | if (ret) |
93 | if (ret) | 93 | goto err_exit_phy; |
94 | goto err_exit_phy; | 94 | ret = phy_power_on(priv->phys[phy_num]); |
95 | ret = phy_power_on(priv->phys[phy_num]); | 95 | if (ret) { |
96 | if (ret) { | 96 | phy_exit(priv->phys[phy_num]); |
97 | phy_exit(priv->phys[phy_num]); | 97 | goto err_exit_phy; |
98 | goto err_exit_phy; | ||
99 | } | ||
100 | } | 98 | } |
101 | } | 99 | } |
102 | 100 | ||
@@ -104,10 +102,8 @@ static int ehci_platform_power_on(struct platform_device *dev) | |||
104 | 102 | ||
105 | err_exit_phy: | 103 | err_exit_phy: |
106 | while (--phy_num >= 0) { | 104 | while (--phy_num >= 0) { |
107 | if (priv->phys[phy_num]) { | 105 | phy_power_off(priv->phys[phy_num]); |
108 | phy_power_off(priv->phys[phy_num]); | 106 | phy_exit(priv->phys[phy_num]); |
109 | phy_exit(priv->phys[phy_num]); | ||
110 | } | ||
111 | } | 107 | } |
112 | err_disable_clks: | 108 | err_disable_clks: |
113 | while (--clk >= 0) | 109 | while (--clk >= 0) |
@@ -123,10 +119,8 @@ static void ehci_platform_power_off(struct platform_device *dev) | |||
123 | int clk, phy_num; | 119 | int clk, phy_num; |
124 | 120 | ||
125 | for (phy_num = 0; phy_num < priv->num_phys; phy_num++) { | 121 | for (phy_num = 0; phy_num < priv->num_phys; phy_num++) { |
126 | if (priv->phys[phy_num]) { | 122 | phy_power_off(priv->phys[phy_num]); |
127 | phy_power_off(priv->phys[phy_num]); | 123 | phy_exit(priv->phys[phy_num]); |
128 | phy_exit(priv->phys[phy_num]); | ||
129 | } | ||
130 | } | 124 | } |
131 | 125 | ||
132 | for (clk = EHCI_MAX_CLKS - 1; clk >= 0; clk--) | 126 | for (clk = EHCI_MAX_CLKS - 1; clk >= 0; clk--) |
@@ -154,7 +148,6 @@ static int ehci_platform_probe(struct platform_device *dev) | |||
154 | struct usb_ehci_pdata *pdata = dev_get_platdata(&dev->dev); | 148 | struct usb_ehci_pdata *pdata = dev_get_platdata(&dev->dev); |
155 | struct ehci_platform_priv *priv; | 149 | struct ehci_platform_priv *priv; |
156 | struct ehci_hcd *ehci; | 150 | struct ehci_hcd *ehci; |
157 | const char *phy_name; | ||
158 | int err, irq, phy_num, clk = 0; | 151 | int err, irq, phy_num, clk = 0; |
159 | 152 | ||
160 | if (usb_disabled()) | 153 | if (usb_disabled()) |
@@ -208,36 +201,22 @@ static int ehci_platform_probe(struct platform_device *dev) | |||
208 | 201 | ||
209 | priv->num_phys = of_count_phandle_with_args(dev->dev.of_node, | 202 | priv->num_phys = of_count_phandle_with_args(dev->dev.of_node, |
210 | "phys", "#phy-cells"); | 203 | "phys", "#phy-cells"); |
211 | priv->num_phys = priv->num_phys > 0 ? priv->num_phys : 1; | ||
212 | 204 | ||
213 | priv->phys = devm_kcalloc(&dev->dev, priv->num_phys, | 205 | if (priv->num_phys > 0) { |
214 | sizeof(struct phy *), GFP_KERNEL); | 206 | priv->phys = devm_kcalloc(&dev->dev, priv->num_phys, |
215 | if (!priv->phys) | 207 | sizeof(struct phy *), GFP_KERNEL); |
216 | return -ENOMEM; | 208 | if (!priv->phys) |
209 | return -ENOMEM; | ||
210 | } else | ||
211 | priv->num_phys = 0; | ||
217 | 212 | ||
218 | for (phy_num = 0; phy_num < priv->num_phys; phy_num++) { | 213 | for (phy_num = 0; phy_num < priv->num_phys; phy_num++) { |
219 | err = of_property_read_string_index( | 214 | priv->phys[phy_num] = devm_of_phy_get_by_index( |
220 | dev->dev.of_node, | 215 | &dev->dev, dev->dev.of_node, phy_num); |
221 | "phy-names", phy_num, | 216 | if (IS_ERR(priv->phys[phy_num])) { |
222 | &phy_name); | 217 | err = PTR_ERR(priv->phys[phy_num]); |
223 | 218 | goto err_put_hcd; | |
224 | if (err < 0) { | 219 | } |
225 | if (priv->num_phys > 1) { | ||
226 | dev_err(&dev->dev, "phy-names not provided"); | ||
227 | goto err_put_hcd; | ||
228 | } else | ||
229 | phy_name = "usb"; | ||
230 | } | ||
231 | |||
232 | priv->phys[phy_num] = devm_phy_get(&dev->dev, | ||
233 | phy_name); | ||
234 | if (IS_ERR(priv->phys[phy_num])) { | ||
235 | err = PTR_ERR(priv->phys[phy_num]); | ||
236 | if ((priv->num_phys > 1) || | ||
237 | (err == -EPROBE_DEFER)) | ||
238 | goto err_put_hcd; | ||
239 | priv->phys[phy_num] = NULL; | ||
240 | } | ||
241 | } | 220 | } |
242 | 221 | ||
243 | for (clk = 0; clk < EHCI_MAX_CLKS; clk++) { | 222 | for (clk = 0; clk < EHCI_MAX_CLKS; clk++) { |
diff --git a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c index 185ceee52d47..c2669f185f65 100644 --- a/drivers/usb/host/ohci-platform.c +++ b/drivers/usb/host/ohci-platform.c | |||
@@ -57,15 +57,13 @@ static int ohci_platform_power_on(struct platform_device *dev) | |||
57 | } | 57 | } |
58 | 58 | ||
59 | for (phy_num = 0; phy_num < priv->num_phys; phy_num++) { | 59 | for (phy_num = 0; phy_num < priv->num_phys; phy_num++) { |
60 | if (priv->phys[phy_num]) { | 60 | ret = phy_init(priv->phys[phy_num]); |
61 | ret = phy_init(priv->phys[phy_num]); | 61 | if (ret) |
62 | if (ret) | 62 | goto err_exit_phy; |
63 | goto err_exit_phy; | 63 | ret = phy_power_on(priv->phys[phy_num]); |
64 | ret = phy_power_on(priv->phys[phy_num]); | 64 | if (ret) { |
65 | if (ret) { | 65 | phy_exit(priv->phys[phy_num]); |
66 | phy_exit(priv->phys[phy_num]); | 66 | goto err_exit_phy; |
67 | goto err_exit_phy; | ||
68 | } | ||
69 | } | 67 | } |
70 | } | 68 | } |
71 | 69 | ||
@@ -73,10 +71,8 @@ static int ohci_platform_power_on(struct platform_device *dev) | |||
73 | 71 | ||
74 | err_exit_phy: | 72 | err_exit_phy: |
75 | while (--phy_num >= 0) { | 73 | while (--phy_num >= 0) { |
76 | if (priv->phys[phy_num]) { | 74 | phy_power_off(priv->phys[phy_num]); |
77 | phy_power_off(priv->phys[phy_num]); | 75 | phy_exit(priv->phys[phy_num]); |
78 | phy_exit(priv->phys[phy_num]); | ||
79 | } | ||
80 | } | 76 | } |
81 | err_disable_clks: | 77 | err_disable_clks: |
82 | while (--clk >= 0) | 78 | while (--clk >= 0) |
@@ -92,10 +88,8 @@ static void ohci_platform_power_off(struct platform_device *dev) | |||
92 | int clk, phy_num; | 88 | int clk, phy_num; |
93 | 89 | ||
94 | for (phy_num = 0; phy_num < priv->num_phys; phy_num++) { | 90 | for (phy_num = 0; phy_num < priv->num_phys; phy_num++) { |
95 | if (priv->phys[phy_num]) { | 91 | phy_power_off(priv->phys[phy_num]); |
96 | phy_power_off(priv->phys[phy_num]); | 92 | phy_exit(priv->phys[phy_num]); |
97 | phy_exit(priv->phys[phy_num]); | ||
98 | } | ||
99 | } | 93 | } |
100 | 94 | ||
101 | for (clk = OHCI_MAX_CLKS - 1; clk >= 0; clk--) | 95 | for (clk = OHCI_MAX_CLKS - 1; clk >= 0; clk--) |
@@ -123,7 +117,6 @@ static int ohci_platform_probe(struct platform_device *dev) | |||
123 | struct usb_ohci_pdata *pdata = dev_get_platdata(&dev->dev); | 117 | struct usb_ohci_pdata *pdata = dev_get_platdata(&dev->dev); |
124 | struct ohci_platform_priv *priv; | 118 | struct ohci_platform_priv *priv; |
125 | struct ohci_hcd *ohci; | 119 | struct ohci_hcd *ohci; |
126 | const char *phy_name; | ||
127 | int err, irq, phy_num, clk = 0; | 120 | int err, irq, phy_num, clk = 0; |
128 | 121 | ||
129 | if (usb_disabled()) | 122 | if (usb_disabled()) |
@@ -174,36 +167,22 @@ static int ohci_platform_probe(struct platform_device *dev) | |||
174 | 167 | ||
175 | priv->num_phys = of_count_phandle_with_args(dev->dev.of_node, | 168 | priv->num_phys = of_count_phandle_with_args(dev->dev.of_node, |
176 | "phys", "#phy-cells"); | 169 | "phys", "#phy-cells"); |
177 | priv->num_phys = priv->num_phys > 0 ? priv->num_phys : 1; | ||
178 | 170 | ||
179 | priv->phys = devm_kcalloc(&dev->dev, priv->num_phys, | 171 | if (priv->num_phys > 0) { |
180 | sizeof(struct phy *), GFP_KERNEL); | 172 | priv->phys = devm_kcalloc(&dev->dev, priv->num_phys, |
181 | if (!priv->phys) | 173 | sizeof(struct phy *), GFP_KERNEL); |
182 | return -ENOMEM; | 174 | if (!priv->phys) |
175 | return -ENOMEM; | ||
176 | } else | ||
177 | priv->num_phys = 0; | ||
183 | 178 | ||
184 | for (phy_num = 0; phy_num < priv->num_phys; phy_num++) { | 179 | for (phy_num = 0; phy_num < priv->num_phys; phy_num++) { |
185 | err = of_property_read_string_index( | 180 | priv->phys[phy_num] = devm_of_phy_get_by_index( |
186 | dev->dev.of_node, | 181 | &dev->dev, dev->dev.of_node, phy_num); |
187 | "phy-names", phy_num, | 182 | if (IS_ERR(priv->phys[phy_num])) { |
188 | &phy_name); | 183 | err = PTR_ERR(priv->phys[phy_num]); |
189 | 184 | goto err_put_hcd; | |
190 | if (err < 0) { | 185 | } |
191 | if (priv->num_phys > 1) { | ||
192 | dev_err(&dev->dev, "phy-names not provided"); | ||
193 | goto err_put_hcd; | ||
194 | } else | ||
195 | phy_name = "usb"; | ||
196 | } | ||
197 | |||
198 | priv->phys[phy_num] = devm_phy_get(&dev->dev, | ||
199 | phy_name); | ||
200 | if (IS_ERR(priv->phys[phy_num])) { | ||
201 | err = PTR_ERR(priv->phys[phy_num]); | ||
202 | if ((priv->num_phys > 1) || | ||
203 | (err == -EPROBE_DEFER)) | ||
204 | goto err_put_hcd; | ||
205 | priv->phys[phy_num] = NULL; | ||
206 | } | ||
207 | } | 186 | } |
208 | 187 | ||
209 | for (clk = 0; clk < OHCI_MAX_CLKS; clk++) { | 188 | for (clk = 0; clk < OHCI_MAX_CLKS; clk++) { |
diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h index a0197fa1b116..8cf05e341cff 100644 --- a/include/linux/phy/phy.h +++ b/include/linux/phy/phy.h | |||
@@ -133,6 +133,8 @@ struct phy *devm_phy_get(struct device *dev, const char *string); | |||
133 | struct phy *devm_phy_optional_get(struct device *dev, const char *string); | 133 | struct phy *devm_phy_optional_get(struct device *dev, const char *string); |
134 | struct phy *devm_of_phy_get(struct device *dev, struct device_node *np, | 134 | struct phy *devm_of_phy_get(struct device *dev, struct device_node *np, |
135 | const char *con_id); | 135 | const char *con_id); |
136 | struct phy *devm_of_phy_get_by_index(struct device *dev, struct device_node *np, | ||
137 | int index); | ||
136 | void phy_put(struct phy *phy); | 138 | void phy_put(struct phy *phy); |
137 | void devm_phy_put(struct device *dev, struct phy *phy); | 139 | void devm_phy_put(struct device *dev, struct phy *phy); |
138 | struct phy *of_phy_get(struct device_node *np, const char *con_id); | 140 | struct phy *of_phy_get(struct device_node *np, const char *con_id); |
@@ -261,6 +263,13 @@ static inline struct phy *devm_of_phy_get(struct device *dev, | |||
261 | return ERR_PTR(-ENOSYS); | 263 | return ERR_PTR(-ENOSYS); |
262 | } | 264 | } |
263 | 265 | ||
266 | static inline struct phy *devm_of_phy_get_by_index(struct device *dev, | ||
267 | struct device_node *np, | ||
268 | int index) | ||
269 | { | ||
270 | return ERR_PTR(-ENOSYS); | ||
271 | } | ||
272 | |||
264 | static inline void phy_put(struct phy *phy) | 273 | static inline void phy_put(struct phy *phy) |
265 | { | 274 | { |
266 | } | 275 | } |