aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorBjorn Helgaas <bhelgaas@google.com>2018-08-15 15:59:10 -0400
committerBjorn Helgaas <bhelgaas@google.com>2018-08-15 15:59:10 -0400
commit37f0e311bca66e9fe74703887c9bb4965914cabf (patch)
tree3be9f14dc28fe04e9823cc12d4bc11c9cf2a6af8 /drivers
parentce342a1aa8c61fe3315b782f6cf4f34d5babce13 (diff)
parenteb1e39f784e83321353314da1b2e8cbb2fceaba9 (diff)
Merge branch 'remotes/lorenzo/pci/cadence'
- Correct the Cadence cdns_pcie_writel() signature (Alan Douglas) - Add Cadence support for optional generic PHYs (Alan Douglas) - Add Cadence power management ops (Alan Douglas) - Remove redundant variable from Cadence driver (Colin Ian King) * remotes/lorenzo/pci/cadence: PCI: pcie-cadence-ep: Remove redundant variable mmc PCI: cadence: Add shutdown callback to host driver PCI: cadence: Add Power Management ops for host and EP dt-bindings: PCI: cadence: Add DT bindings for optional PHYs PCI: cadence: Add generic PHY support to host and EP drivers PCI: cadence: Update cdns_pcie_writel() function signature
Diffstat (limited to 'drivers')
-rw-r--r--drivers/pci/controller/pcie-cadence-ep.c18
-rw-r--r--drivers/pci/controller/pcie-cadence-host.c33
-rw-r--r--drivers/pci/controller/pcie-cadence.c123
-rw-r--r--drivers/pci/controller/pcie-cadence.h13
4 files changed, 183 insertions, 4 deletions
diff --git a/drivers/pci/controller/pcie-cadence-ep.c b/drivers/pci/controller/pcie-cadence-ep.c
index e3fe4124e3af..04fe76c3d59d 100644
--- a/drivers/pci/controller/pcie-cadence-ep.c
+++ b/drivers/pci/controller/pcie-cadence-ep.c
@@ -238,7 +238,7 @@ static int cdns_pcie_ep_get_msi(struct pci_epc *epc, u8 fn)
238 struct cdns_pcie_ep *ep = epc_get_drvdata(epc); 238 struct cdns_pcie_ep *ep = epc_get_drvdata(epc);
239 struct cdns_pcie *pcie = &ep->pcie; 239 struct cdns_pcie *pcie = &ep->pcie;
240 u32 cap = CDNS_PCIE_EP_FUNC_MSI_CAP_OFFSET; 240 u32 cap = CDNS_PCIE_EP_FUNC_MSI_CAP_OFFSET;
241 u16 flags, mmc, mme; 241 u16 flags, mme;
242 242
243 /* Validate that the MSI feature is actually enabled. */ 243 /* Validate that the MSI feature is actually enabled. */
244 flags = cdns_pcie_ep_fn_readw(pcie, fn, cap + PCI_MSI_FLAGS); 244 flags = cdns_pcie_ep_fn_readw(pcie, fn, cap + PCI_MSI_FLAGS);
@@ -249,7 +249,6 @@ static int cdns_pcie_ep_get_msi(struct pci_epc *epc, u8 fn)
249 * Get the Multiple Message Enable bitfield from the Message Control 249 * Get the Multiple Message Enable bitfield from the Message Control
250 * register. 250 * register.
251 */ 251 */
252 mmc = (flags & PCI_MSI_FLAGS_QMASK) >> 1;
253 mme = (flags & PCI_MSI_FLAGS_QSIZE) >> 4; 252 mme = (flags & PCI_MSI_FLAGS_QSIZE) >> 4;
254 253
255 return mme; 254 return mme;
@@ -439,6 +438,7 @@ static int cdns_pcie_ep_probe(struct platform_device *pdev)
439 struct pci_epc *epc; 438 struct pci_epc *epc;
440 struct resource *res; 439 struct resource *res;
441 int ret; 440 int ret;
441 int phy_count;
442 442
443 ep = devm_kzalloc(dev, sizeof(*ep), GFP_KERNEL); 443 ep = devm_kzalloc(dev, sizeof(*ep), GFP_KERNEL);
444 if (!ep) 444 if (!ep)
@@ -473,6 +473,12 @@ static int cdns_pcie_ep_probe(struct platform_device *pdev)
473 if (!ep->ob_addr) 473 if (!ep->ob_addr)
474 return -ENOMEM; 474 return -ENOMEM;
475 475
476 ret = cdns_pcie_init_phy(dev, pcie);
477 if (ret) {
478 dev_err(dev, "failed to init phy\n");
479 return ret;
480 }
481 platform_set_drvdata(pdev, pcie);
476 pm_runtime_enable(dev); 482 pm_runtime_enable(dev);
477 ret = pm_runtime_get_sync(dev); 483 ret = pm_runtime_get_sync(dev);
478 if (ret < 0) { 484 if (ret < 0) {
@@ -521,6 +527,10 @@ static int cdns_pcie_ep_probe(struct platform_device *pdev)
521 527
522 err_get_sync: 528 err_get_sync:
523 pm_runtime_disable(dev); 529 pm_runtime_disable(dev);
530 cdns_pcie_disable_phy(pcie);
531 phy_count = pcie->phy_count;
532 while (phy_count--)
533 device_link_del(pcie->link[phy_count]);
524 534
525 return ret; 535 return ret;
526} 536}
@@ -528,6 +538,7 @@ static int cdns_pcie_ep_probe(struct platform_device *pdev)
528static void cdns_pcie_ep_shutdown(struct platform_device *pdev) 538static void cdns_pcie_ep_shutdown(struct platform_device *pdev)
529{ 539{
530 struct device *dev = &pdev->dev; 540 struct device *dev = &pdev->dev;
541 struct cdns_pcie *pcie = dev_get_drvdata(dev);
531 int ret; 542 int ret;
532 543
533 ret = pm_runtime_put_sync(dev); 544 ret = pm_runtime_put_sync(dev);
@@ -536,13 +547,14 @@ static void cdns_pcie_ep_shutdown(struct platform_device *pdev)
536 547
537 pm_runtime_disable(dev); 548 pm_runtime_disable(dev);
538 549
539 /* The PCIe controller can't be disabled. */ 550 cdns_pcie_disable_phy(pcie);
540} 551}
541 552
542static struct platform_driver cdns_pcie_ep_driver = { 553static struct platform_driver cdns_pcie_ep_driver = {
543 .driver = { 554 .driver = {
544 .name = "cdns-pcie-ep", 555 .name = "cdns-pcie-ep",
545 .of_match_table = cdns_pcie_ep_of_match, 556 .of_match_table = cdns_pcie_ep_of_match,
557 .pm = &cdns_pcie_pm_ops,
546 }, 558 },
547 .probe = cdns_pcie_ep_probe, 559 .probe = cdns_pcie_ep_probe,
548 .shutdown = cdns_pcie_ep_shutdown, 560 .shutdown = cdns_pcie_ep_shutdown,
diff --git a/drivers/pci/controller/pcie-cadence-host.c b/drivers/pci/controller/pcie-cadence-host.c
index a4ebbd37b553..ec394f6a19c8 100644
--- a/drivers/pci/controller/pcie-cadence-host.c
+++ b/drivers/pci/controller/pcie-cadence-host.c
@@ -58,6 +58,11 @@ static void __iomem *cdns_pci_map_bus(struct pci_bus *bus, unsigned int devfn,
58 58
59 return pcie->reg_base + (where & 0xfff); 59 return pcie->reg_base + (where & 0xfff);
60 } 60 }
61 /* Check that the link is up */
62 if (!(cdns_pcie_readl(pcie, CDNS_PCIE_LM_BASE) & 0x1))
63 return NULL;
64 /* Clear AXI link-down status */
65 cdns_pcie_writel(pcie, CDNS_PCIE_AT_LINKDOWN, 0x0);
61 66
62 /* Update Output registers for AXI region 0. */ 67 /* Update Output registers for AXI region 0. */
63 addr0 = CDNS_PCIE_AT_OB_REGION_PCI_ADDR0_NBITS(12) | 68 addr0 = CDNS_PCIE_AT_OB_REGION_PCI_ADDR0_NBITS(12) |
@@ -239,6 +244,7 @@ static int cdns_pcie_host_probe(struct platform_device *pdev)
239 struct cdns_pcie *pcie; 244 struct cdns_pcie *pcie;
240 struct resource *res; 245 struct resource *res;
241 int ret; 246 int ret;
247 int phy_count;
242 248
243 bridge = devm_pci_alloc_host_bridge(dev, sizeof(*rc)); 249 bridge = devm_pci_alloc_host_bridge(dev, sizeof(*rc));
244 if (!bridge) 250 if (!bridge)
@@ -290,6 +296,13 @@ static int cdns_pcie_host_probe(struct platform_device *pdev)
290 } 296 }
291 pcie->mem_res = res; 297 pcie->mem_res = res;
292 298
299 ret = cdns_pcie_init_phy(dev, pcie);
300 if (ret) {
301 dev_err(dev, "failed to init phy\n");
302 return ret;
303 }
304 platform_set_drvdata(pdev, pcie);
305
293 pm_runtime_enable(dev); 306 pm_runtime_enable(dev);
294 ret = pm_runtime_get_sync(dev); 307 ret = pm_runtime_get_sync(dev);
295 if (ret < 0) { 308 if (ret < 0) {
@@ -322,15 +335,35 @@ static int cdns_pcie_host_probe(struct platform_device *pdev)
322 335
323 err_get_sync: 336 err_get_sync:
324 pm_runtime_disable(dev); 337 pm_runtime_disable(dev);
338 cdns_pcie_disable_phy(pcie);
339 phy_count = pcie->phy_count;
340 while (phy_count--)
341 device_link_del(pcie->link[phy_count]);
325 342
326 return ret; 343 return ret;
327} 344}
328 345
346static void cdns_pcie_shutdown(struct platform_device *pdev)
347{
348 struct device *dev = &pdev->dev;
349 struct cdns_pcie *pcie = dev_get_drvdata(dev);
350 int ret;
351
352 ret = pm_runtime_put_sync(dev);
353 if (ret < 0)
354 dev_dbg(dev, "pm_runtime_put_sync failed\n");
355
356 pm_runtime_disable(dev);
357 cdns_pcie_disable_phy(pcie);
358}
359
329static struct platform_driver cdns_pcie_host_driver = { 360static struct platform_driver cdns_pcie_host_driver = {
330 .driver = { 361 .driver = {
331 .name = "cdns-pcie-host", 362 .name = "cdns-pcie-host",
332 .of_match_table = cdns_pcie_host_of_match, 363 .of_match_table = cdns_pcie_host_of_match,
364 .pm = &cdns_pcie_pm_ops,
333 }, 365 },
334 .probe = cdns_pcie_host_probe, 366 .probe = cdns_pcie_host_probe,
367 .shutdown = cdns_pcie_shutdown,
335}; 368};
336builtin_platform_driver(cdns_pcie_host_driver); 369builtin_platform_driver(cdns_pcie_host_driver);
diff --git a/drivers/pci/controller/pcie-cadence.c b/drivers/pci/controller/pcie-cadence.c
index 138d113eb45d..86f1b002c846 100644
--- a/drivers/pci/controller/pcie-cadence.c
+++ b/drivers/pci/controller/pcie-cadence.c
@@ -124,3 +124,126 @@ void cdns_pcie_reset_outbound_region(struct cdns_pcie *pcie, u32 r)
124 cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_CPU_ADDR0(r), 0); 124 cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_CPU_ADDR0(r), 0);
125 cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_CPU_ADDR1(r), 0); 125 cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_CPU_ADDR1(r), 0);
126} 126}
127
128void cdns_pcie_disable_phy(struct cdns_pcie *pcie)
129{
130 int i = pcie->phy_count;
131
132 while (i--) {
133 phy_power_off(pcie->phy[i]);
134 phy_exit(pcie->phy[i]);
135 }
136}
137
138int cdns_pcie_enable_phy(struct cdns_pcie *pcie)
139{
140 int ret;
141 int i;
142
143 for (i = 0; i < pcie->phy_count; i++) {
144 ret = phy_init(pcie->phy[i]);
145 if (ret < 0)
146 goto err_phy;
147
148 ret = phy_power_on(pcie->phy[i]);
149 if (ret < 0) {
150 phy_exit(pcie->phy[i]);
151 goto err_phy;
152 }
153 }
154
155 return 0;
156
157err_phy:
158 while (--i >= 0) {
159 phy_power_off(pcie->phy[i]);
160 phy_exit(pcie->phy[i]);
161 }
162
163 return ret;
164}
165
166int cdns_pcie_init_phy(struct device *dev, struct cdns_pcie *pcie)
167{
168 struct device_node *np = dev->of_node;
169 int phy_count;
170 struct phy **phy;
171 struct device_link **link;
172 int i;
173 int ret;
174 const char *name;
175
176 phy_count = of_property_count_strings(np, "phy-names");
177 if (phy_count < 1) {
178 dev_err(dev, "no phy-names. PHY will not be initialized\n");
179 pcie->phy_count = 0;
180 return 0;
181 }
182
183 phy = devm_kzalloc(dev, sizeof(*phy) * phy_count, GFP_KERNEL);
184 if (!phy)
185 return -ENOMEM;
186
187 link = devm_kzalloc(dev, sizeof(*link) * phy_count, GFP_KERNEL);
188 if (!link)
189 return -ENOMEM;
190
191 for (i = 0; i < phy_count; i++) {
192 of_property_read_string_index(np, "phy-names", i, &name);
193 phy[i] = devm_phy_optional_get(dev, name);
194 if (IS_ERR(phy))
195 return PTR_ERR(phy);
196
197 link[i] = device_link_add(dev, &phy[i]->dev, DL_FLAG_STATELESS);
198 if (!link[i]) {
199 ret = -EINVAL;
200 goto err_link;
201 }
202 }
203
204 pcie->phy_count = phy_count;
205 pcie->phy = phy;
206 pcie->link = link;
207
208 ret = cdns_pcie_enable_phy(pcie);
209 if (ret)
210 goto err_link;
211
212 return 0;
213
214err_link:
215 while (--i >= 0)
216 device_link_del(link[i]);
217
218 return ret;
219}
220
221#ifdef CONFIG_PM_SLEEP
222static int cdns_pcie_suspend_noirq(struct device *dev)
223{
224 struct cdns_pcie *pcie = dev_get_drvdata(dev);
225
226 cdns_pcie_disable_phy(pcie);
227
228 return 0;
229}
230
231static int cdns_pcie_resume_noirq(struct device *dev)
232{
233 struct cdns_pcie *pcie = dev_get_drvdata(dev);
234 int ret;
235
236 ret = cdns_pcie_enable_phy(pcie);
237 if (ret) {
238 dev_err(dev, "failed to enable phy\n");
239 return ret;
240 }
241
242 return 0;
243}
244#endif
245
246const struct dev_pm_ops cdns_pcie_pm_ops = {
247 SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(cdns_pcie_suspend_noirq,
248 cdns_pcie_resume_noirq)
249};
diff --git a/drivers/pci/controller/pcie-cadence.h b/drivers/pci/controller/pcie-cadence.h
index 4bb27333b05c..ae6bf2a2b3d3 100644
--- a/drivers/pci/controller/pcie-cadence.h
+++ b/drivers/pci/controller/pcie-cadence.h
@@ -8,6 +8,7 @@
8 8
9#include <linux/kernel.h> 9#include <linux/kernel.h>
10#include <linux/pci.h> 10#include <linux/pci.h>
11#include <linux/phy/phy.h>
11 12
12/* 13/*
13 * Local Management Registers 14 * Local Management Registers
@@ -165,6 +166,9 @@
165#define CDNS_PCIE_AT_IB_RP_BAR_ADDR1(bar) \ 166#define CDNS_PCIE_AT_IB_RP_BAR_ADDR1(bar) \
166 (CDNS_PCIE_AT_BASE + 0x0804 + (bar) * 0x0008) 167 (CDNS_PCIE_AT_BASE + 0x0804 + (bar) * 0x0008)
167 168
169/* AXI link down register */
170#define CDNS_PCIE_AT_LINKDOWN (CDNS_PCIE_AT_BASE + 0x0824)
171
168enum cdns_pcie_rp_bar { 172enum cdns_pcie_rp_bar {
169 RP_BAR0, 173 RP_BAR0,
170 RP_BAR1, 174 RP_BAR1,
@@ -229,6 +233,9 @@ struct cdns_pcie {
229 struct resource *mem_res; 233 struct resource *mem_res;
230 bool is_rc; 234 bool is_rc;
231 u8 bus; 235 u8 bus;
236 int phy_count;
237 struct phy **phy;
238 struct device_link **link;
232}; 239};
233 240
234/* Register access */ 241/* Register access */
@@ -279,7 +286,7 @@ static inline void cdns_pcie_ep_fn_writew(struct cdns_pcie *pcie, u8 fn,
279} 286}
280 287
281static inline void cdns_pcie_ep_fn_writel(struct cdns_pcie *pcie, u8 fn, 288static inline void cdns_pcie_ep_fn_writel(struct cdns_pcie *pcie, u8 fn,
282 u32 reg, u16 value) 289 u32 reg, u32 value)
283{ 290{
284 writel(value, pcie->reg_base + CDNS_PCIE_EP_FUNC_BASE(fn) + reg); 291 writel(value, pcie->reg_base + CDNS_PCIE_EP_FUNC_BASE(fn) + reg);
285} 292}
@@ -307,5 +314,9 @@ void cdns_pcie_set_outbound_region_for_normal_msg(struct cdns_pcie *pcie, u8 fn,
307 u32 r, u64 cpu_addr); 314 u32 r, u64 cpu_addr);
308 315
309void cdns_pcie_reset_outbound_region(struct cdns_pcie *pcie, u32 r); 316void cdns_pcie_reset_outbound_region(struct cdns_pcie *pcie, u32 r);
317void cdns_pcie_disable_phy(struct cdns_pcie *pcie);
318int cdns_pcie_enable_phy(struct cdns_pcie *pcie);
319int cdns_pcie_init_phy(struct device *dev, struct cdns_pcie *pcie);
320extern const struct dev_pm_ops cdns_pcie_pm_ops;
310 321
311#endif /* _PCIE_CADENCE_H */ 322#endif /* _PCIE_CADENCE_H */