Skip to content

Commit

Permalink
r8169: Get and enable optional ether_clk clock
Browse files Browse the repository at this point in the history
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 d31fd43 ("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 <[email protected]>
Cc: Carlo Caione <[email protected]>
Reported-by: Johannes Stezenbach <[email protected]>
Acked-by: Stephen Boyd <[email protected]>
Reviewed-by: Andy Shevchenko <[email protected]>
Signed-off-by: Hans de Goede <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
jwrdegoede authored and davem330 committed Sep 18, 2018
1 parent b1e3454 commit c2f6f3e
Showing 1 changed file with 33 additions and 0 deletions.
33 changes: 33 additions & 0 deletions drivers/net/ethernet/realtek/r8169.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <linux/pci.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/ethtool.h>
#include <linux/phy.h>
Expand Down Expand Up @@ -665,6 +666,7 @@ struct rtl8169_private {

u16 event_slow;
const struct rtl_coalesce_info *coalesce_info;
struct clk *clk;

struct mdio_ops {
void (*write)(struct rtl8169_private *, int, int);
Expand Down Expand Up @@ -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)
{
const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data;
Expand All @@ -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->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) */
rc = pcim_enable_device(pdev);
if (rc < 0) {
Expand Down

0 comments on commit c2f6f3e

Please sign in to comment.