Commit c2f6f3ee authored by Hans de Goede's avatar Hans de Goede Committed by David S. Miller

r8169: Get and enable optional ether_clk clock

On some boards a platform clock is used as clock for the r8169 chip,
this commit adds support for getting and enabling this clock (assuming
it has an "ether_clk" alias set on it).

This is related to commit d31fd43c ("clk: x86: Do not gate clocks
enabled by the firmware") which is a previous attempt to fix this for some
x86 boards, but this causes all Cherry Trail SoC using boards to not reach
there lowest power states when suspending.

This commit (together with an atom-pmc-clk driver commit adding the alias)
fixes things properly by making the r8169 get the clock and enable it when
it needs it.

Buglink: https://bugzilla.kernel.org/show_bug.cgi?id=193891#c102
Buglink: https://bugzilla.kernel.org/show_bug.cgi?id=196861
Cc: Johannes Stezenbach <js@sig21.net>
Cc: Carlo Caione <carlo@endlessm.com>
Reported-by: default avatarJohannes Stezenbach <js@sig21.net>
Acked-by: default avatarStephen Boyd <sboyd@kernel.org>
Reviewed-by: default avatarAndy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: default avatarHans de Goede <hdegoede@redhat.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b1e3454d
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
#include <linux/clk.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/ethtool.h> #include <linux/ethtool.h>
#include <linux/phy.h> #include <linux/phy.h>
...@@ -665,6 +666,7 @@ struct rtl8169_private { ...@@ -665,6 +666,7 @@ struct rtl8169_private {
u16 event_slow; u16 event_slow;
const struct rtl_coalesce_info *coalesce_info; const struct rtl_coalesce_info *coalesce_info;
struct clk *clk;
struct mdio_ops { struct mdio_ops {
void (*write)(struct rtl8169_private *, int, int); void (*write)(struct rtl8169_private *, int, int);
...@@ -7262,6 +7264,11 @@ static int rtl_jumbo_max(struct rtl8169_private *tp) ...@@ -7262,6 +7264,11 @@ static int rtl_jumbo_max(struct rtl8169_private *tp)
} }
} }
static void rtl_disable_clk(void *data)
{
clk_disable_unprepare(data);
}
static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{ {
const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data; const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data;
...@@ -7282,6 +7289,32 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -7282,6 +7289,32 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
tp->msg_enable = netif_msg_init(debug.msg_enable, R8169_MSG_DEFAULT); tp->msg_enable = netif_msg_init(debug.msg_enable, R8169_MSG_DEFAULT);
tp->supports_gmii = cfg->has_gmii; tp->supports_gmii = cfg->has_gmii;
/* Get the *optional* external "ether_clk" used on some boards */
tp->clk = devm_clk_get(&pdev->dev, "ether_clk");
if (IS_ERR(tp->clk)) {
rc = PTR_ERR(tp->clk);
if (rc == -ENOENT) {
/* clk-core allows NULL (for suspend / resume) */
tp->clk = NULL;
} else if (rc == -EPROBE_DEFER) {
return rc;
} else {
dev_err(&pdev->dev, "failed to get clk: %d\n", rc);
return rc;
}
} else {
rc = clk_prepare_enable(tp->clk);
if (rc) {
dev_err(&pdev->dev, "failed to enable clk: %d\n", rc);
return rc;
}
rc = devm_add_action_or_reset(&pdev->dev, rtl_disable_clk,
tp->clk);
if (rc)
return rc;
}
/* enable device (incl. PCI PM wakeup and hotplug setup) */ /* enable device (incl. PCI PM wakeup and hotplug setup) */
rc = pcim_enable_device(pdev); rc = pcim_enable_device(pdev);
if (rc < 0) { if (rc < 0) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment