diff options
Diffstat (limited to 'drivers/net/phy')
-rw-r--r-- | drivers/net/phy/sfp.c | 35 |
1 files changed, 27 insertions, 8 deletions
diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c index d4635c2178d1..554acc869c25 100644 --- a/drivers/net/phy/sfp.c +++ b/drivers/net/phy/sfp.c @@ -1,4 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 +#include <linux/acpi.h> #include <linux/ctype.h> #include <linux/delay.h> #include <linux/gpio/consumer.h> @@ -1782,6 +1783,7 @@ static void sfp_cleanup(void *data) static int sfp_probe(struct platform_device *pdev) { const struct sff_data *sff; + struct i2c_adapter *i2c; struct sfp *sfp; bool poll = false; int irq, err, i; @@ -1801,7 +1803,6 @@ static int sfp_probe(struct platform_device *pdev) if (pdev->dev.of_node) { struct device_node *node = pdev->dev.of_node; const struct of_device_id *id; - struct i2c_adapter *i2c; struct device_node *np; id = of_match_node(sfp_of_match, node); @@ -1818,14 +1819,32 @@ static int sfp_probe(struct platform_device *pdev) i2c = of_find_i2c_adapter_by_node(np); of_node_put(np); - if (!i2c) - return -EPROBE_DEFER; - - err = sfp_i2c_configure(sfp, i2c); - if (err < 0) { - i2c_put_adapter(i2c); - return err; + } else if (has_acpi_companion(&pdev->dev)) { + struct acpi_device *adev = ACPI_COMPANION(&pdev->dev); + struct fwnode_handle *fw = acpi_fwnode_handle(adev); + struct fwnode_reference_args args; + struct acpi_handle *acpi_handle; + int ret; + + ret = acpi_node_get_property_reference(fw, "i2c-bus", 0, &args); + if (ACPI_FAILURE(ret) || !is_acpi_device_node(args.fwnode)) { + dev_err(&pdev->dev, "missing 'i2c-bus' property\n"); + return -ENODEV; } + + acpi_handle = ACPI_HANDLE_FWNODE(args.fwnode); + i2c = i2c_acpi_find_adapter_by_handle(acpi_handle); + } else { + return -EINVAL; + } + + if (!i2c) + return -EPROBE_DEFER; + + err = sfp_i2c_configure(sfp, i2c); + if (err < 0) { + i2c_put_adapter(i2c); + return err; } for (i = 0; i < GPIO_MAX; i++) |