aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2018-09-17 21:47:58 -0400
committerDavid S. Miller <davem@davemloft.net>2018-09-17 21:47:58 -0400
commit89bfd48d679ed4f2ce4cbd9a8f8cbcd041c9050c (patch)
tree265778341e820a569f935aa6e9dec41c02bdd177
parent0866cd15029baa3331ba347794053472306e8eb3 (diff)
parent648e921888ad96ea3dc922739e96716ad3225d7f (diff)
Merge branch 'r8169-clk-fixes'
Hans de Goede says: ==================== r8169 (x86) clk fixes to fix S0ix not being reached This series adds code to the r8169 ethernet driver to get and enable an external clock if present, avoiding the need for a hack in the clk-pmc-atom driver where that clock was left on continuesly causing x86 some devices to not reach deep power saving states (S0ix) when suspended causing to them to quickly drain their battery while suspended. The 3 commits in this series need to be merged in order to avoid regressions while bisecting. The clk-pmc-atom driver does not see much changes (it was last touched over a year ago). So the clk maintainers have agreed with merging all 3 patches through the net tree. All 3 patches have Stephen Boyd's Acked-by for this purpose. This v2 of the series only had some minor tweaks done to the commit messages and is ready for merging through the net tree now. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/clk/x86/clk-pmc-atom.c18
-rw-r--r--drivers/net/ethernet/realtek/r8169.c33
2 files changed, 44 insertions, 7 deletions
diff --git a/drivers/clk/x86/clk-pmc-atom.c b/drivers/clk/x86/clk-pmc-atom.c
index 08ef69945ffb..d977193842df 100644
--- a/drivers/clk/x86/clk-pmc-atom.c
+++ b/drivers/clk/x86/clk-pmc-atom.c
@@ -55,6 +55,7 @@ struct clk_plt_data {
55 u8 nparents; 55 u8 nparents;
56 struct clk_plt *clks[PMC_CLK_NUM]; 56 struct clk_plt *clks[PMC_CLK_NUM];
57 struct clk_lookup *mclk_lookup; 57 struct clk_lookup *mclk_lookup;
58 struct clk_lookup *ether_clk_lookup;
58}; 59};
59 60
60/* Return an index in parent table */ 61/* Return an index in parent table */
@@ -186,13 +187,6 @@ static struct clk_plt *plt_clk_register(struct platform_device *pdev, int id,
186 pclk->reg = base + PMC_CLK_CTL_OFFSET + id * PMC_CLK_CTL_SIZE; 187 pclk->reg = base + PMC_CLK_CTL_OFFSET + id * PMC_CLK_CTL_SIZE;
187 spin_lock_init(&pclk->lock); 188 spin_lock_init(&pclk->lock);
188 189
189 /*
190 * If the clock was already enabled by the firmware mark it as critical
191 * to avoid it being gated by the clock framework if no driver owns it.
192 */
193 if (plt_clk_is_enabled(&pclk->hw))
194 init.flags |= CLK_IS_CRITICAL;
195
196 ret = devm_clk_hw_register(&pdev->dev, &pclk->hw); 190 ret = devm_clk_hw_register(&pdev->dev, &pclk->hw);
197 if (ret) { 191 if (ret) {
198 pclk = ERR_PTR(ret); 192 pclk = ERR_PTR(ret);
@@ -351,11 +345,20 @@ static int plt_clk_probe(struct platform_device *pdev)
351 goto err_unreg_clk_plt; 345 goto err_unreg_clk_plt;
352 } 346 }
353 347
348 data->ether_clk_lookup = clkdev_hw_create(&data->clks[4]->hw,
349 "ether_clk", NULL);
350 if (!data->ether_clk_lookup) {
351 err = -ENOMEM;
352 goto err_drop_mclk;
353 }
354
354 plt_clk_free_parent_names_loop(parent_names, data->nparents); 355 plt_clk_free_parent_names_loop(parent_names, data->nparents);
355 356
356 platform_set_drvdata(pdev, data); 357 platform_set_drvdata(pdev, data);
357 return 0; 358 return 0;
358 359
360err_drop_mclk:
361 clkdev_drop(data->mclk_lookup);
359err_unreg_clk_plt: 362err_unreg_clk_plt:
360 plt_clk_unregister_loop(data, i); 363 plt_clk_unregister_loop(data, i);
361 plt_clk_unregister_parents(data); 364 plt_clk_unregister_parents(data);
@@ -369,6 +372,7 @@ static int plt_clk_remove(struct platform_device *pdev)
369 372
370 data = platform_get_drvdata(pdev); 373 data = platform_get_drvdata(pdev);
371 374
375 clkdev_drop(data->ether_clk_lookup);
372 clkdev_drop(data->mclk_lookup); 376 clkdev_drop(data->mclk_lookup);
373 plt_clk_unregister_loop(data, PMC_CLK_NUM); 377 plt_clk_unregister_loop(data, PMC_CLK_NUM);
374 plt_clk_unregister_parents(data); 378 plt_clk_unregister_parents(data);
diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
index b0a803e96634..bb529ff2ca81 100644
--- a/drivers/net/ethernet/realtek/r8169.c
+++ b/drivers/net/ethernet/realtek/r8169.c
@@ -13,6 +13,7 @@
13#include <linux/pci.h> 13#include <linux/pci.h>
14#include <linux/netdevice.h> 14#include <linux/netdevice.h>
15#include <linux/etherdevice.h> 15#include <linux/etherdevice.h>
16#include <linux/clk.h>
16#include <linux/delay.h> 17#include <linux/delay.h>
17#include <linux/ethtool.h> 18#include <linux/ethtool.h>
18#include <linux/phy.h> 19#include <linux/phy.h>
@@ -665,6 +666,7 @@ struct rtl8169_private {
665 666
666 u16 event_slow; 667 u16 event_slow;
667 const struct rtl_coalesce_info *coalesce_info; 668 const struct rtl_coalesce_info *coalesce_info;
669 struct clk *clk;
668 670
669 struct mdio_ops { 671 struct mdio_ops {
670 void (*write)(struct rtl8169_private *, int, int); 672 void (*write)(struct rtl8169_private *, int, int);
@@ -7262,6 +7264,11 @@ static int rtl_jumbo_max(struct rtl8169_private *tp)
7262 } 7264 }
7263} 7265}
7264 7266
7267static void rtl_disable_clk(void *data)
7268{
7269 clk_disable_unprepare(data);
7270}
7271
7265static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) 7272static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
7266{ 7273{
7267 const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data; 7274 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 tp->msg_enable = netif_msg_init(debug.msg_enable, R8169_MSG_DEFAULT); 7289 tp->msg_enable = netif_msg_init(debug.msg_enable, R8169_MSG_DEFAULT);
7283 tp->supports_gmii = cfg->has_gmii; 7290 tp->supports_gmii = cfg->has_gmii;
7284 7291
7292 /* Get the *optional* external "ether_clk" used on some boards */
7293 tp->clk = devm_clk_get(&pdev->dev, "ether_clk");
7294 if (IS_ERR(tp->clk)) {
7295 rc = PTR_ERR(tp->clk);
7296 if (rc == -ENOENT) {
7297 /* clk-core allows NULL (for suspend / resume) */
7298 tp->clk = NULL;
7299 } else if (rc == -EPROBE_DEFER) {
7300 return rc;
7301 } else {
7302 dev_err(&pdev->dev, "failed to get clk: %d\n", rc);
7303 return rc;
7304 }
7305 } else {
7306 rc = clk_prepare_enable(tp->clk);
7307 if (rc) {
7308 dev_err(&pdev->dev, "failed to enable clk: %d\n", rc);
7309 return rc;
7310 }
7311
7312 rc = devm_add_action_or_reset(&pdev->dev, rtl_disable_clk,
7313 tp->clk);
7314 if (rc)
7315 return rc;
7316 }
7317
7285 /* enable device (incl. PCI PM wakeup and hotplug setup) */ 7318 /* enable device (incl. PCI PM wakeup and hotplug setup) */
7286 rc = pcim_enable_device(pdev); 7319 rc = pcim_enable_device(pdev);
7287 if (rc < 0) { 7320 if (rc < 0) {