1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
From 336a4404b02b564930725715659ca583b8a58a6b Mon Sep 17 00:00:00 2001
From: Miquel Raynal <miquel.raynal@bootlin.com>
Date: Wed, 31 Aug 2022 15:59:39 +0200
Subject: [PATCH 8/9] PCI: aardvark: Add clock support
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The IP relies on a gated clock. When we will add S2RAM support, this
clock will need to be resumed before any PCIe registers are
accessed. Add support for this clock.
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Signed-off-by: Pali Rohár <pali@kernel.org>
Signed-off-by: Marek Behún <kabel@kernel.org>
---
drivers/pci/controller/pci-aardvark.c | 32 +++++++++++++++++++++++++++
1 file changed, 32 insertions(+)
diff --git a/drivers/pci/controller/pci-aardvark.c b/drivers/pci/controller/pci-aardvark.c
index cf493d62b889..17aed65aab91 100644
--- a/drivers/pci/controller/pci-aardvark.c
+++ b/drivers/pci/controller/pci-aardvark.c
@@ -9,6 +9,7 @@
*/
#include <linux/bitfield.h>
+#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/interrupt.h>
@@ -298,6 +299,7 @@ struct advk_pcie {
struct timer_list link_irq_timer;
struct pci_bridge_emul bridge;
struct gpio_desc *reset_gpio;
+ struct clk *clk;
struct phy *phy;
};
@@ -1828,6 +1830,29 @@ static int advk_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
return of_irq_parse_and_map_pci(dev, slot, pin);
}
+static int advk_pcie_setup_clk(struct advk_pcie *pcie)
+{
+ struct device *dev = &pcie->pdev->dev;
+ int ret;
+
+ pcie->clk = devm_clk_get(dev, NULL);
+ if (IS_ERR(pcie->clk) && (PTR_ERR(pcie->clk) == -EPROBE_DEFER))
+ return PTR_ERR(pcie->clk);
+
+ /* Old bindings miss the clock handle */
+ if (IS_ERR(pcie->clk)) {
+ dev_warn(dev, "Clock unavailable (%ld)\n", PTR_ERR(pcie->clk));
+ pcie->clk = NULL;
+ return 0;
+ }
+
+ ret = clk_prepare_enable(pcie->clk);
+ if (ret)
+ dev_err(dev, "Clock initialization failed (%d)\n", ret);
+
+ return ret;
+}
+
static void advk_pcie_disable_phy(struct advk_pcie *pcie)
{
phy_power_off(pcie->phy);
@@ -2021,6 +2046,10 @@ static int advk_pcie_probe(struct platform_device *pdev)
slot_power_limit / 1000,
(slot_power_limit / 100) % 10);
+ ret = advk_pcie_setup_clk(pcie);
+ if (ret)
+ return ret;
+
ret = advk_pcie_setup_phy(pcie);
if (ret)
return ret;
@@ -2143,6 +2172,9 @@ static int advk_pcie_remove(struct platform_device *pdev)
/* Disable phy */
advk_pcie_disable_phy(pcie);
+ /* Disable clock */
+ clk_disable_unprepare(pcie->clk);
+
return 0;
}
--
2.34.1
|