aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2017-12-05 12:51:20 -0500
committerDavid S. Miller <davem@davemloft.net>2017-12-05 12:51:20 -0500
commit75223d81164b90c0a2af078b227e768d6f4751c1 (patch)
tree5db80649c4b0bb9bad0e74794c02a6dbc51b820e
parent62b32379fd124fea521484ba7e220d8a449f0b59 (diff)
parent096457b5523bbbb371c0099d4db5663fa084494a (diff)
Merge branch 'phylib-hard-resetting-devices'
Geert Uytterhoeven says: ==================== Teach phylib hard-resetting devices This patch series adds optional PHY reset support to phylib. The first two patches are destined for David's net-next tree. They add core PHY reset code, and update a driver that currently uses its own reset code. The last two patches are destined for Simon's renesas tree. They add properties to describe the EthernetAVB PHY reset topology to the common Salvator-X/XS and ULCB DTS files, which solves two issues: 1. On Salvator-XS, the enable pin of the regulator providing PHY power is connected to PRESETn, and PSCI powers down the SoC during system suspend. Hence a PHY reset is needed to restore network functionality after system resume. 2. Linux should not rely on the boot loader having reset the PHY, but should reset the PHY during driver probe. Changes compared to v3: - Remove Florian's Acked-by, - Add missing #include <linux/gpio/consumer.h>, - Re-add the gpiod check, as the dummy gpiod_set_value() for !GPIOLIB does not ignore NULL, and calls WARN_ON(1), - Do not reassert the reset signal if {mdio,phy}_probe() or phy_device_register() succeeded, as that may destroy initial setup, - Do not deassert the reset signal in {mdio,phy}_remove(), as it should already be deasserted, - Bring the PHY back into reset state in phy_device_remove(), - Move/consolidate GPIO descriptor acquiring code from of_mdiobus_register_phy() and of_mdiobus_register_device() to mdiobus_register_device(). Note that this changes behavior slightly, in that the reset signal is now also asserted when called from of_mdiobus_register_device(). - Add Reviewed-by, Changes compared to v2, as sent by Sergei Shtylyov: - Fix fwnode_get_named_gpiod() call due to added parameters (which allowed to eliminate the gpiod_direction_output() call), - Rebased, refreshed, reworded, - Take over from Sergei, - Add Acked-by, - Remove unneeded gpiod check, as gpiod_set_value() handles NULL fine, - Handle fwnode_get_named_gpiod() errors correctly: - -ENOENT is ignored (the GPIO is optional), and turned into NULL, which allowed to remove all later !IS_ERR() checks, - Other errors (incl. -EPROBE_DEFER) are propagated, - Extract DTS patches from series "[PATCH 0/4] ravb: Add PHY reset support" (https://www.spinics.net/lists/netdev/msg457308.html), and incorporate in this series, after moving reset-gpios from the ethernet to the ethernet-phy node. Given (1) the new reset-gpios DT property in the PHY node follows established practises, (2) the DT binding change in the first patch has been acked by Rob, and (3) the DTS patch does not cause any regressions if it is applied before the PHY driver patches, the DTS patches can be applied independently. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--Documentation/devicetree/bindings/net/phy.txt2
-rw-r--r--drivers/net/ethernet/cadence/macb.h1
-rw-r--r--drivers/net/ethernet/cadence/macb_main.c21
-rw-r--r--drivers/net/phy/at803x.c18
-rw-r--r--drivers/net/phy/mdio_bus.c21
-rw-r--r--drivers/net/phy/mdio_device.c25
-rw-r--r--drivers/net/phy/phy_device.c32
-rw-r--r--include/linux/mdio.h3
-rw-r--r--include/linux/phy.h5
9 files changed, 87 insertions, 41 deletions
diff --git a/Documentation/devicetree/bindings/net/phy.txt b/Documentation/devicetree/bindings/net/phy.txt
index 77d0b2a61ffa..c05479f5ac7c 100644
--- a/Documentation/devicetree/bindings/net/phy.txt
+++ b/Documentation/devicetree/bindings/net/phy.txt
@@ -53,6 +53,8 @@ Optional Properties:
53 to ensure the integrated PHY is used. The absence of this property indicates 53 to ensure the integrated PHY is used. The absence of this property indicates
54 the muxers should be configured so that the external PHY is used. 54 the muxers should be configured so that the external PHY is used.
55 55
56- reset-gpios: The GPIO phandle and specifier for the PHY reset signal.
57
56Example: 58Example:
57 59
58ethernet-phy@0 { 60ethernet-phy@0 {
diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h
index 3165c2ba58f9..c50c5ec49b1d 100644
--- a/drivers/net/ethernet/cadence/macb.h
+++ b/drivers/net/ethernet/cadence/macb.h
@@ -1171,7 +1171,6 @@ struct macb {
1171 unsigned int dma_burst_length; 1171 unsigned int dma_burst_length;
1172 1172
1173 phy_interface_t phy_interface; 1173 phy_interface_t phy_interface;
1174 struct gpio_desc *reset_gpio;
1175 1174
1176 /* AT91RM9200 transmit */ 1175 /* AT91RM9200 transmit */
1177 struct sk_buff *skb; /* holds skb until xmit interrupt completes */ 1176 struct sk_buff *skb; /* holds skb until xmit interrupt completes */
diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c
index 8af325ef542d..ebfeab853bf4 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -3803,7 +3803,6 @@ static int macb_probe(struct platform_device *pdev)
3803 = macb_config->clk_init; 3803 = macb_config->clk_init;
3804 int (*init)(struct platform_device *) = macb_config->init; 3804 int (*init)(struct platform_device *) = macb_config->init;
3805 struct device_node *np = pdev->dev.of_node; 3805 struct device_node *np = pdev->dev.of_node;
3806 struct device_node *phy_node;
3807 struct clk *pclk, *hclk = NULL, *tx_clk = NULL, *rx_clk = NULL; 3806 struct clk *pclk, *hclk = NULL, *tx_clk = NULL, *rx_clk = NULL;
3808 unsigned int queue_mask, num_queues; 3807 unsigned int queue_mask, num_queues;
3809 struct macb_platform_data *pdata; 3808 struct macb_platform_data *pdata;
@@ -3909,18 +3908,6 @@ static int macb_probe(struct platform_device *pdev)
3909 else 3908 else
3910 macb_get_hwaddr(bp); 3909 macb_get_hwaddr(bp);
3911 3910
3912 /* Power up the PHY if there is a GPIO reset */
3913 phy_node = of_get_next_available_child(np, NULL);
3914 if (phy_node) {
3915 int gpio = of_get_named_gpio(phy_node, "reset-gpios", 0);
3916
3917 if (gpio_is_valid(gpio)) {
3918 bp->reset_gpio = gpio_to_desc(gpio);
3919 gpiod_direction_output(bp->reset_gpio, 1);
3920 }
3921 }
3922 of_node_put(phy_node);
3923
3924 err = of_get_phy_mode(np); 3911 err = of_get_phy_mode(np);
3925 if (err < 0) { 3912 if (err < 0) {
3926 pdata = dev_get_platdata(&pdev->dev); 3913 pdata = dev_get_platdata(&pdev->dev);
@@ -3967,10 +3954,6 @@ err_out_unregister_mdio:
3967 of_phy_deregister_fixed_link(np); 3954 of_phy_deregister_fixed_link(np);
3968 mdiobus_free(bp->mii_bus); 3955 mdiobus_free(bp->mii_bus);
3969 3956
3970 /* Shutdown the PHY if there is a GPIO reset */
3971 if (bp->reset_gpio)
3972 gpiod_set_value(bp->reset_gpio, 0);
3973
3974err_out_free_netdev: 3957err_out_free_netdev:
3975 free_netdev(dev); 3958 free_netdev(dev);
3976 3959
@@ -4001,10 +3984,6 @@ static int macb_remove(struct platform_device *pdev)
4001 dev->phydev = NULL; 3984 dev->phydev = NULL;
4002 mdiobus_free(bp->mii_bus); 3985 mdiobus_free(bp->mii_bus);
4003 3986
4004 /* Shutdown the PHY if there is a GPIO reset */
4005 if (bp->reset_gpio)
4006 gpiod_set_value(bp->reset_gpio, 0);
4007
4008 unregister_netdev(dev); 3987 unregister_netdev(dev);
4009 clk_disable_unprepare(bp->tx_clk); 3988 clk_disable_unprepare(bp->tx_clk);
4010 clk_disable_unprepare(bp->hclk); 3989 clk_disable_unprepare(bp->hclk);
diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c
index de7dd6566df7..29da7a3c7a37 100644
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -71,7 +71,6 @@ MODULE_LICENSE("GPL");
71 71
72struct at803x_priv { 72struct at803x_priv {
73 bool phy_reset:1; 73 bool phy_reset:1;
74 struct gpio_desc *gpiod_reset;
75}; 74};
76 75
77struct at803x_context { 76struct at803x_context {
@@ -254,22 +253,11 @@ static int at803x_probe(struct phy_device *phydev)
254{ 253{
255 struct device *dev = &phydev->mdio.dev; 254 struct device *dev = &phydev->mdio.dev;
256 struct at803x_priv *priv; 255 struct at803x_priv *priv;
257 struct gpio_desc *gpiod_reset;
258 256
259 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 257 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
260 if (!priv) 258 if (!priv)
261 return -ENOMEM; 259 return -ENOMEM;
262 260
263 if (phydev->drv->phy_id != ATH8030_PHY_ID)
264 goto does_not_require_reset_workaround;
265
266 gpiod_reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
267 if (IS_ERR(gpiod_reset))
268 return PTR_ERR(gpiod_reset);
269
270 priv->gpiod_reset = gpiod_reset;
271
272does_not_require_reset_workaround:
273 phydev->priv = priv; 261 phydev->priv = priv;
274 262
275 return 0; 263 return 0;
@@ -343,14 +331,14 @@ static void at803x_link_change_notify(struct phy_device *phydev)
343 * cannot recover from by software. 331 * cannot recover from by software.
344 */ 332 */
345 if (phydev->state == PHY_NOLINK) { 333 if (phydev->state == PHY_NOLINK) {
346 if (priv->gpiod_reset && !priv->phy_reset) { 334 if (phydev->mdio.reset && !priv->phy_reset) {
347 struct at803x_context context; 335 struct at803x_context context;
348 336
349 at803x_context_save(phydev, &context); 337 at803x_context_save(phydev, &context);
350 338
351 gpiod_set_value(priv->gpiod_reset, 1); 339 phy_device_reset(phydev, 1);
352 msleep(1); 340 msleep(1);
353 gpiod_set_value(priv->gpiod_reset, 0); 341 phy_device_reset(phydev, 0);
354 msleep(1); 342 msleep(1);
355 343
356 at803x_context_restore(phydev, &context); 344 at803x_context_restore(phydev, &context);
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index 2df7b62c1a36..8f8b7747c54b 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -38,6 +38,7 @@
38#include <linux/phy.h> 38#include <linux/phy.h>
39#include <linux/io.h> 39#include <linux/io.h>
40#include <linux/uaccess.h> 40#include <linux/uaccess.h>
41#include <linux/gpio/consumer.h>
41 42
42#include <asm/irq.h> 43#include <asm/irq.h>
43 44
@@ -48,9 +49,26 @@
48 49
49int mdiobus_register_device(struct mdio_device *mdiodev) 50int mdiobus_register_device(struct mdio_device *mdiodev)
50{ 51{
52 struct gpio_desc *gpiod = NULL;
53
51 if (mdiodev->bus->mdio_map[mdiodev->addr]) 54 if (mdiodev->bus->mdio_map[mdiodev->addr])
52 return -EBUSY; 55 return -EBUSY;
53 56
57 /* Deassert the optional reset signal */
58 if (mdiodev->dev.of_node)
59 gpiod = fwnode_get_named_gpiod(&mdiodev->dev.of_node->fwnode,
60 "reset-gpios", 0, GPIOD_OUT_LOW,
61 "PHY reset");
62 if (PTR_ERR(gpiod) == -ENOENT)
63 gpiod = NULL;
64 else if (IS_ERR(gpiod))
65 return PTR_ERR(gpiod);
66
67 mdiodev->reset = gpiod;
68
69 /* Assert the reset signal again */
70 mdio_device_reset(mdiodev, 1);
71
54 mdiodev->bus->mdio_map[mdiodev->addr] = mdiodev; 72 mdiodev->bus->mdio_map[mdiodev->addr] = mdiodev;
55 73
56 return 0; 74 return 0;
@@ -420,6 +438,9 @@ void mdiobus_unregister(struct mii_bus *bus)
420 if (!mdiodev) 438 if (!mdiodev)
421 continue; 439 continue;
422 440
441 if (mdiodev->reset)
442 gpiod_put(mdiodev->reset);
443
423 mdiodev->device_remove(mdiodev); 444 mdiodev->device_remove(mdiodev);
424 mdiodev->device_free(mdiodev); 445 mdiodev->device_free(mdiodev);
425 } 446 }
diff --git a/drivers/net/phy/mdio_device.c b/drivers/net/phy/mdio_device.c
index e24f28924af8..75d97dd9fb28 100644
--- a/drivers/net/phy/mdio_device.c
+++ b/drivers/net/phy/mdio_device.c
@@ -12,6 +12,8 @@
12#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 12#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
13 13
14#include <linux/errno.h> 14#include <linux/errno.h>
15#include <linux/gpio.h>
16#include <linux/gpio/consumer.h>
15#include <linux/init.h> 17#include <linux/init.h>
16#include <linux/interrupt.h> 18#include <linux/interrupt.h>
17#include <linux/kernel.h> 19#include <linux/kernel.h>
@@ -114,6 +116,13 @@ void mdio_device_remove(struct mdio_device *mdiodev)
114} 116}
115EXPORT_SYMBOL(mdio_device_remove); 117EXPORT_SYMBOL(mdio_device_remove);
116 118
119void mdio_device_reset(struct mdio_device *mdiodev, int value)
120{
121 if (mdiodev->reset)
122 gpiod_set_value(mdiodev->reset, value);
123}
124EXPORT_SYMBOL(mdio_device_reset);
125
117/** 126/**
118 * mdio_probe - probe an MDIO device 127 * mdio_probe - probe an MDIO device
119 * @dev: device to probe 128 * @dev: device to probe
@@ -128,8 +137,16 @@ static int mdio_probe(struct device *dev)
128 struct mdio_driver *mdiodrv = to_mdio_driver(drv); 137 struct mdio_driver *mdiodrv = to_mdio_driver(drv);
129 int err = 0; 138 int err = 0;
130 139
131 if (mdiodrv->probe) 140 if (mdiodrv->probe) {
141 /* Deassert the reset signal */
142 mdio_device_reset(mdiodev, 0);
143
132 err = mdiodrv->probe(mdiodev); 144 err = mdiodrv->probe(mdiodev);
145 if (err) {
146 /* Assert the reset signal */
147 mdio_device_reset(mdiodev, 1);
148 }
149 }
133 150
134 return err; 151 return err;
135} 152}
@@ -140,9 +157,13 @@ static int mdio_remove(struct device *dev)
140 struct device_driver *drv = mdiodev->dev.driver; 157 struct device_driver *drv = mdiodev->dev.driver;
141 struct mdio_driver *mdiodrv = to_mdio_driver(drv); 158 struct mdio_driver *mdiodrv = to_mdio_driver(drv);
142 159
143 if (mdiodrv->remove) 160 if (mdiodrv->remove) {
144 mdiodrv->remove(mdiodev); 161 mdiodrv->remove(mdiodev);
145 162
163 /* Assert the reset signal */
164 mdio_device_reset(mdiodev, 1);
165 }
166
146 return 0; 167 return 0;
147} 168}
148 169
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 8154fb706751..1de5e242b8b4 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -632,6 +632,9 @@ int phy_device_register(struct phy_device *phydev)
632 if (err) 632 if (err)
633 return err; 633 return err;
634 634
635 /* Deassert the reset signal */
636 phy_device_reset(phydev, 0);
637
635 /* Run all of the fixups for this PHY */ 638 /* Run all of the fixups for this PHY */
636 err = phy_scan_fixups(phydev); 639 err = phy_scan_fixups(phydev);
637 if (err) { 640 if (err) {
@@ -650,6 +653,9 @@ int phy_device_register(struct phy_device *phydev)
650 return 0; 653 return 0;
651 654
652 out: 655 out:
656 /* Assert the reset signal */
657 phy_device_reset(phydev, 1);
658
653 mdiobus_unregister_device(&phydev->mdio); 659 mdiobus_unregister_device(&phydev->mdio);
654 return err; 660 return err;
655} 661}
@@ -666,6 +672,10 @@ EXPORT_SYMBOL(phy_device_register);
666void phy_device_remove(struct phy_device *phydev) 672void phy_device_remove(struct phy_device *phydev)
667{ 673{
668 device_del(&phydev->mdio.dev); 674 device_del(&phydev->mdio.dev);
675
676 /* Assert the reset signal */
677 phy_device_reset(phydev, 1);
678
669 mdiobus_unregister_device(&phydev->mdio); 679 mdiobus_unregister_device(&phydev->mdio);
670} 680}
671EXPORT_SYMBOL(phy_device_remove); 681EXPORT_SYMBOL(phy_device_remove);
@@ -849,6 +859,9 @@ int phy_init_hw(struct phy_device *phydev)
849{ 859{
850 int ret = 0; 860 int ret = 0;
851 861
862 /* Deassert the reset signal */
863 phy_device_reset(phydev, 0);
864
852 if (!phydev->drv || !phydev->drv->config_init) 865 if (!phydev->drv || !phydev->drv->config_init)
853 return 0; 866 return 0;
854 867
@@ -1126,6 +1139,9 @@ void phy_detach(struct phy_device *phydev)
1126 put_device(&phydev->mdio.dev); 1139 put_device(&phydev->mdio.dev);
1127 if (ndev_owner != bus->owner) 1140 if (ndev_owner != bus->owner)
1128 module_put(bus->owner); 1141 module_put(bus->owner);
1142
1143 /* Assert the reset signal */
1144 phy_device_reset(phydev, 1);
1129} 1145}
1130EXPORT_SYMBOL(phy_detach); 1146EXPORT_SYMBOL(phy_detach);
1131 1147
@@ -1811,8 +1827,16 @@ static int phy_probe(struct device *dev)
1811 /* Set the state to READY by default */ 1827 /* Set the state to READY by default */
1812 phydev->state = PHY_READY; 1828 phydev->state = PHY_READY;
1813 1829
1814 if (phydev->drv->probe) 1830 if (phydev->drv->probe) {
1831 /* Deassert the reset signal */
1832 phy_device_reset(phydev, 0);
1833
1815 err = phydev->drv->probe(phydev); 1834 err = phydev->drv->probe(phydev);
1835 if (err) {
1836 /* Assert the reset signal */
1837 phy_device_reset(phydev, 1);
1838 }
1839 }
1816 1840
1817 mutex_unlock(&phydev->lock); 1841 mutex_unlock(&phydev->lock);
1818 1842
@@ -1829,8 +1853,12 @@ static int phy_remove(struct device *dev)
1829 phydev->state = PHY_DOWN; 1853 phydev->state = PHY_DOWN;
1830 mutex_unlock(&phydev->lock); 1854 mutex_unlock(&phydev->lock);
1831 1855
1832 if (phydev->drv && phydev->drv->remove) 1856 if (phydev->drv && phydev->drv->remove) {
1833 phydev->drv->remove(phydev); 1857 phydev->drv->remove(phydev);
1858
1859 /* Assert the reset signal */
1860 phy_device_reset(phydev, 1);
1861 }
1834 phydev->drv = NULL; 1862 phydev->drv = NULL;
1835 1863
1836 return 0; 1864 return 0;
diff --git a/include/linux/mdio.h b/include/linux/mdio.h
index ca08ab16ecdc..92d4e55ffe67 100644
--- a/include/linux/mdio.h
+++ b/include/linux/mdio.h
@@ -12,6 +12,7 @@
12#include <uapi/linux/mdio.h> 12#include <uapi/linux/mdio.h>
13#include <linux/mod_devicetable.h> 13#include <linux/mod_devicetable.h>
14 14
15struct gpio_desc;
15struct mii_bus; 16struct mii_bus;
16 17
17/* Multiple levels of nesting are possible. However typically this is 18/* Multiple levels of nesting are possible. However typically this is
@@ -39,6 +40,7 @@ struct mdio_device {
39 /* Bus address of the MDIO device (0-31) */ 40 /* Bus address of the MDIO device (0-31) */
40 int addr; 41 int addr;
41 int flags; 42 int flags;
43 struct gpio_desc *reset;
42}; 44};
43#define to_mdio_device(d) container_of(d, struct mdio_device, dev) 45#define to_mdio_device(d) container_of(d, struct mdio_device, dev)
44 46
@@ -71,6 +73,7 @@ void mdio_device_free(struct mdio_device *mdiodev);
71struct mdio_device *mdio_device_create(struct mii_bus *bus, int addr); 73struct mdio_device *mdio_device_create(struct mii_bus *bus, int addr);
72int mdio_device_register(struct mdio_device *mdiodev); 74int mdio_device_register(struct mdio_device *mdiodev);
73void mdio_device_remove(struct mdio_device *mdiodev); 75void mdio_device_remove(struct mdio_device *mdiodev);
76void mdio_device_reset(struct mdio_device *mdiodev, int value);
74int mdio_driver_register(struct mdio_driver *drv); 77int mdio_driver_register(struct mdio_driver *drv);
75void mdio_driver_unregister(struct mdio_driver *drv); 78void mdio_driver_unregister(struct mdio_driver *drv);
76int mdio_device_bus_match(struct device *dev, struct device_driver *drv); 79int mdio_device_bus_match(struct device *dev, struct device_driver *drv);
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 7570cb838410..d3037e2ffbc4 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -854,6 +854,11 @@ int phy_aneg_done(struct phy_device *phydev);
854int phy_stop_interrupts(struct phy_device *phydev); 854int phy_stop_interrupts(struct phy_device *phydev);
855int phy_restart_aneg(struct phy_device *phydev); 855int phy_restart_aneg(struct phy_device *phydev);
856 856
857static inline void phy_device_reset(struct phy_device *phydev, int value)
858{
859 mdio_device_reset(&phydev->mdio, value);
860}
861
857#define phydev_err(_phydev, format, args...) \ 862#define phydev_err(_phydev, format, args...) \
858 dev_err(&_phydev->mdio.dev, format, ##args) 863 dev_err(&_phydev->mdio.dev, format, ##args)
859 864