mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-12 05:24:12 +08:00
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 d31fd43c0f
("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: Johannes Stezenbach <js@sig21.net>
Acked-by: Stephen Boyd <sboyd@kernel.org>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
b1e3454d39
commit
c2f6f3ee7f
@ -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>
|
||||
@ -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);
|
||||
@ -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;
|
||||
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user