aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/dwc/pci-keystone.c
diff options
context:
space:
mode:
authorKishon Vijay Abraham I <kishon@ti.com>2017-01-06 07:52:48 -0500
committerBjorn Helgaas <bhelgaas@google.com>2017-02-21 15:59:53 -0500
commit950bf6388bc22c2749b8b66c501df1462639d6bd (patch)
tree958e246da4ba9726ae57f63378ffe758d1970e1b /drivers/pci/dwc/pci-keystone.c
parent656795c8873f93956a031d5db6fb08cf6168ebb0 (diff)
PCI: Move DesignWare IP support to new drivers/pci/dwc/ directory
Group all the PCI drivers that use DesignWare core in dwc directory. dwc IP is capable of operating in both host mode and device mode and keeping it inside the *host* directory is misleading. Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Acked-by: Jingoo Han <jingoohan1@gmail.com> Acked-By: Joao Pinto <jpinto@synopsys.com> Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> Cc: Minghuan Lian <minghuan.Lian@freescale.com> Cc: Mingkai Hu <mingkai.hu@freescale.com> Cc: Roy Zang <tie-fei.zang@freescale.com> Cc: Richard Zhu <hongxing.zhu@nxp.com> Cc: Lucas Stach <l.stach@pengutronix.de> Cc: Murali Karicheri <m-karicheri2@ti.com> Cc: Pratyush Anand <pratyush.anand@gmail.com> Cc: Niklas Cassel <niklas.cassel@axis.com> Cc: Jesper Nilsson <jesper.nilsson@axis.com> Cc: Zhou Wang <wangzhou1@hisilicon.com> Cc: Gabriele Paoloni <gabriele.paoloni@huawei.com> Cc: Stanimir Varbanov <svarbanov@mm-sol.com>
Diffstat (limited to 'drivers/pci/dwc/pci-keystone.c')
-rw-r--r--drivers/pci/dwc/pci-keystone.c444
1 files changed, 444 insertions, 0 deletions
diff --git a/drivers/pci/dwc/pci-keystone.c b/drivers/pci/dwc/pci-keystone.c
new file mode 100644
index 000000000000..043c19a05da1
--- /dev/null
+++ b/drivers/pci/dwc/pci-keystone.c
@@ -0,0 +1,444 @@
1/*
2 * PCIe host controller driver for Texas Instruments Keystone SoCs
3 *
4 * Copyright (C) 2013-2014 Texas Instruments., Ltd.
5 * http://www.ti.com
6 *
7 * Author: Murali Karicheri <m-karicheri2@ti.com>
8 * Implementation based on pci-exynos.c and pcie-designware.c
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14
15#include <linux/irqchip/chained_irq.h>
16#include <linux/clk.h>
17#include <linux/delay.h>
18#include <linux/interrupt.h>
19#include <linux/irqdomain.h>
20#include <linux/init.h>
21#include <linux/msi.h>
22#include <linux/of_irq.h>
23#include <linux/of.h>
24#include <linux/of_pci.h>
25#include <linux/platform_device.h>
26#include <linux/phy/phy.h>
27#include <linux/resource.h>
28#include <linux/signal.h>
29
30#include "pcie-designware.h"
31#include "pci-keystone.h"
32
33#define DRIVER_NAME "keystone-pcie"
34
35/* driver specific constants */
36#define MAX_MSI_HOST_IRQS 8
37#define MAX_LEGACY_HOST_IRQS 4
38
39/* DEV_STAT_CTRL */
40#define PCIE_CAP_BASE 0x70
41
42/* PCIE controller device IDs */
43#define PCIE_RC_K2HK 0xb008
44#define PCIE_RC_K2E 0xb009
45#define PCIE_RC_K2L 0xb00a
46
47#define to_keystone_pcie(x) container_of(x, struct keystone_pcie, pp)
48
49static void quirk_limit_mrrs(struct pci_dev *dev)
50{
51 struct pci_bus *bus = dev->bus;
52 struct pci_dev *bridge = bus->self;
53 static const struct pci_device_id rc_pci_devids[] = {
54 { PCI_DEVICE(PCI_VENDOR_ID_TI, PCIE_RC_K2HK),
55 .class = PCI_CLASS_BRIDGE_PCI << 8, .class_mask = ~0, },
56 { PCI_DEVICE(PCI_VENDOR_ID_TI, PCIE_RC_K2E),
57 .class = PCI_CLASS_BRIDGE_PCI << 8, .class_mask = ~0, },
58 { PCI_DEVICE(PCI_VENDOR_ID_TI, PCIE_RC_K2L),
59 .class = PCI_CLASS_BRIDGE_PCI << 8, .class_mask = ~0, },
60 { 0, },
61 };
62
63 if (pci_is_root_bus(bus))
64 return;
65
66 /* look for the host bridge */
67 while (!pci_is_root_bus(bus)) {
68 bridge = bus->self;
69 bus = bus->parent;
70 }
71
72 if (bridge) {
73 /*
74 * Keystone PCI controller has a h/w limitation of
75 * 256 bytes maximum read request size. It can't handle
76 * anything higher than this. So force this limit on
77 * all downstream devices.
78 */
79 if (pci_match_id(rc_pci_devids, bridge)) {
80 if (pcie_get_readrq(dev) > 256) {
81 dev_info(&dev->dev, "limiting MRRS to 256\n");
82 pcie_set_readrq(dev, 256);
83 }
84 }
85 }
86}
87DECLARE_PCI_FIXUP_ENABLE(PCI_ANY_ID, PCI_ANY_ID, quirk_limit_mrrs);
88
89static int ks_pcie_establish_link(struct keystone_pcie *ks_pcie)
90{
91 struct pcie_port *pp = &ks_pcie->pp;
92 struct device *dev = pp->dev;
93 unsigned int retries;
94
95 dw_pcie_setup_rc(pp);
96
97 if (dw_pcie_link_up(pp)) {
98 dev_err(dev, "Link already up\n");
99 return 0;
100 }
101
102 /* check if the link is up or not */
103 for (retries = 0; retries < 5; retries++) {
104 ks_dw_pcie_initiate_link_train(ks_pcie);
105 if (!dw_pcie_wait_for_link(pp))
106 return 0;
107 }
108
109 dev_err(dev, "phy link never came up\n");
110 return -ETIMEDOUT;
111}
112
113static void ks_pcie_msi_irq_handler(struct irq_desc *desc)
114{
115 unsigned int irq = irq_desc_get_irq(desc);
116 struct keystone_pcie *ks_pcie = irq_desc_get_handler_data(desc);
117 u32 offset = irq - ks_pcie->msi_host_irqs[0];
118 struct pcie_port *pp = &ks_pcie->pp;
119 struct device *dev = pp->dev;
120 struct irq_chip *chip = irq_desc_get_chip(desc);
121
122 dev_dbg(dev, "%s, irq %d\n", __func__, irq);
123
124 /*
125 * The chained irq handler installation would have replaced normal
126 * interrupt driver handler so we need to take care of mask/unmask and
127 * ack operation.
128 */
129 chained_irq_enter(chip, desc);
130 ks_dw_pcie_handle_msi_irq(ks_pcie, offset);
131 chained_irq_exit(chip, desc);
132}
133
134/**
135 * ks_pcie_legacy_irq_handler() - Handle legacy interrupt
136 * @irq: IRQ line for legacy interrupts
137 * @desc: Pointer to irq descriptor
138 *
139 * Traverse through pending legacy interrupts and invoke handler for each. Also
140 * takes care of interrupt controller level mask/ack operation.
141 */
142static void ks_pcie_legacy_irq_handler(struct irq_desc *desc)
143{
144 unsigned int irq = irq_desc_get_irq(desc);
145 struct keystone_pcie *ks_pcie = irq_desc_get_handler_data(desc);
146 struct pcie_port *pp = &ks_pcie->pp;
147 struct device *dev = pp->dev;
148 u32 irq_offset = irq - ks_pcie->legacy_host_irqs[0];
149 struct irq_chip *chip = irq_desc_get_chip(desc);
150
151 dev_dbg(dev, ": Handling legacy irq %d\n", irq);
152
153 /*
154 * The chained irq handler installation would have replaced normal
155 * interrupt driver handler so we need to take care of mask/unmask and
156 * ack operation.
157 */
158 chained_irq_enter(chip, desc);
159 ks_dw_pcie_handle_legacy_irq(ks_pcie, irq_offset);
160 chained_irq_exit(chip, desc);
161}
162
163static int ks_pcie_get_irq_controller_info(struct keystone_pcie *ks_pcie,
164 char *controller, int *num_irqs)
165{
166 int temp, max_host_irqs, legacy = 1, *host_irqs;
167 struct device *dev = ks_pcie->pp.dev;
168 struct device_node *np_pcie = dev->of_node, **np_temp;
169
170 if (!strcmp(controller, "msi-interrupt-controller"))
171 legacy = 0;
172
173 if (legacy) {
174 np_temp = &ks_pcie->legacy_intc_np;
175 max_host_irqs = MAX_LEGACY_HOST_IRQS;
176 host_irqs = &ks_pcie->legacy_host_irqs[0];
177 } else {
178 np_temp = &ks_pcie->msi_intc_np;
179 max_host_irqs = MAX_MSI_HOST_IRQS;
180 host_irqs = &ks_pcie->msi_host_irqs[0];
181 }
182
183 /* interrupt controller is in a child node */
184 *np_temp = of_find_node_by_name(np_pcie, controller);
185 if (!(*np_temp)) {
186 dev_err(dev, "Node for %s is absent\n", controller);
187 return -EINVAL;
188 }
189
190 temp = of_irq_count(*np_temp);
191 if (!temp) {
192 dev_err(dev, "No IRQ entries in %s\n", controller);
193 return -EINVAL;
194 }
195
196 if (temp > max_host_irqs)
197 dev_warn(dev, "Too many %s interrupts defined %u\n",
198 (legacy ? "legacy" : "MSI"), temp);
199
200 /*
201 * support upto max_host_irqs. In dt from index 0 to 3 (legacy) or 0 to
202 * 7 (MSI)
203 */
204 for (temp = 0; temp < max_host_irqs; temp++) {
205 host_irqs[temp] = irq_of_parse_and_map(*np_temp, temp);
206 if (!host_irqs[temp])
207 break;
208 }
209
210 if (temp) {
211 *num_irqs = temp;
212 return 0;
213 }
214
215 return -EINVAL;
216}
217
218static void ks_pcie_setup_interrupts(struct keystone_pcie *ks_pcie)
219{
220 int i;
221
222 /* Legacy IRQ */
223 for (i = 0; i < ks_pcie->num_legacy_host_irqs; i++) {
224 irq_set_chained_handler_and_data(ks_pcie->legacy_host_irqs[i],
225 ks_pcie_legacy_irq_handler,
226 ks_pcie);
227 }
228 ks_dw_pcie_enable_legacy_irqs(ks_pcie);
229
230 /* MSI IRQ */
231 if (IS_ENABLED(CONFIG_PCI_MSI)) {
232 for (i = 0; i < ks_pcie->num_msi_host_irqs; i++) {
233 irq_set_chained_handler_and_data(ks_pcie->msi_host_irqs[i],
234 ks_pcie_msi_irq_handler,
235 ks_pcie);
236 }
237 }
238
239 if (ks_pcie->error_irq > 0)
240 ks_dw_pcie_enable_error_irq(ks_pcie);
241}
242
243/*
244 * When a PCI device does not exist during config cycles, keystone host gets a
245 * bus error instead of returning 0xffffffff. This handler always returns 0
246 * for this kind of faults.
247 */
248static int keystone_pcie_fault(unsigned long addr, unsigned int fsr,
249 struct pt_regs *regs)
250{
251 unsigned long instr = *(unsigned long *) instruction_pointer(regs);
252
253 if ((instr & 0x0e100090) == 0x00100090) {
254 int reg = (instr >> 12) & 15;
255
256 regs->uregs[reg] = -1;
257 regs->ARM_pc += 4;
258 }
259
260 return 0;
261}
262
263static void __init ks_pcie_host_init(struct pcie_port *pp)
264{
265 struct keystone_pcie *ks_pcie = to_keystone_pcie(pp);
266 u32 val;
267
268 ks_pcie_establish_link(ks_pcie);
269 ks_dw_pcie_setup_rc_app_regs(ks_pcie);
270 ks_pcie_setup_interrupts(ks_pcie);
271 writew(PCI_IO_RANGE_TYPE_32 | (PCI_IO_RANGE_TYPE_32 << 8),
272 pp->dbi_base + PCI_IO_BASE);
273
274 /* update the Vendor ID */
275 writew(ks_pcie->device_id, pp->dbi_base + PCI_DEVICE_ID);
276
277 /* update the DEV_STAT_CTRL to publish right mrrs */
278 val = readl(pp->dbi_base + PCIE_CAP_BASE + PCI_EXP_DEVCTL);
279 val &= ~PCI_EXP_DEVCTL_READRQ;
280 /* set the mrrs to 256 bytes */
281 val |= BIT(12);
282 writel(val, pp->dbi_base + PCIE_CAP_BASE + PCI_EXP_DEVCTL);
283
284 /*
285 * PCIe access errors that result into OCP errors are caught by ARM as
286 * "External aborts"
287 */
288 hook_fault_code(17, keystone_pcie_fault, SIGBUS, 0,
289 "Asynchronous external abort");
290}
291
292static struct pcie_host_ops keystone_pcie_host_ops = {
293 .rd_other_conf = ks_dw_pcie_rd_other_conf,
294 .wr_other_conf = ks_dw_pcie_wr_other_conf,
295 .link_up = ks_dw_pcie_link_up,
296 .host_init = ks_pcie_host_init,
297 .msi_set_irq = ks_dw_pcie_msi_set_irq,
298 .msi_clear_irq = ks_dw_pcie_msi_clear_irq,
299 .get_msi_addr = ks_dw_pcie_get_msi_addr,
300 .msi_host_init = ks_dw_pcie_msi_host_init,
301 .scan_bus = ks_dw_pcie_v3_65_scan_bus,
302};
303
304static irqreturn_t pcie_err_irq_handler(int irq, void *priv)
305{
306 struct keystone_pcie *ks_pcie = priv;
307
308 return ks_dw_pcie_handle_error_irq(ks_pcie);
309}
310
311static int __init ks_add_pcie_port(struct keystone_pcie *ks_pcie,
312 struct platform_device *pdev)
313{
314 struct pcie_port *pp = &ks_pcie->pp;
315 struct device *dev = pp->dev;
316 int ret;
317
318 ret = ks_pcie_get_irq_controller_info(ks_pcie,
319 "legacy-interrupt-controller",
320 &ks_pcie->num_legacy_host_irqs);
321 if (ret)
322 return ret;
323
324 if (IS_ENABLED(CONFIG_PCI_MSI)) {
325 ret = ks_pcie_get_irq_controller_info(ks_pcie,
326 "msi-interrupt-controller",
327 &ks_pcie->num_msi_host_irqs);
328 if (ret)
329 return ret;
330 }
331
332 /*
333 * Index 0 is the platform interrupt for error interrupt
334 * from RC. This is optional.
335 */
336 ks_pcie->error_irq = irq_of_parse_and_map(ks_pcie->np, 0);
337 if (ks_pcie->error_irq <= 0)
338 dev_info(dev, "no error IRQ defined\n");
339 else {
340 ret = request_irq(ks_pcie->error_irq, pcie_err_irq_handler,
341 IRQF_SHARED, "pcie-error-irq", ks_pcie);
342 if (ret < 0) {
343 dev_err(dev, "failed to request error IRQ %d\n",
344 ks_pcie->error_irq);
345 return ret;
346 }
347 }
348
349 pp->root_bus_nr = -1;
350 pp->ops = &keystone_pcie_host_ops;
351 ret = ks_dw_pcie_host_init(ks_pcie, ks_pcie->msi_intc_np);
352 if (ret) {
353 dev_err(dev, "failed to initialize host\n");
354 return ret;
355 }
356
357 return 0;
358}
359
360static const struct of_device_id ks_pcie_of_match[] = {
361 {
362 .type = "pci",
363 .compatible = "ti,keystone-pcie",
364 },
365 { },
366};
367
368static int __exit ks_pcie_remove(struct platform_device *pdev)
369{
370 struct keystone_pcie *ks_pcie = platform_get_drvdata(pdev);
371
372 clk_disable_unprepare(ks_pcie->clk);
373
374 return 0;
375}
376
377static int __init ks_pcie_probe(struct platform_device *pdev)
378{
379 struct device *dev = &pdev->dev;
380 struct keystone_pcie *ks_pcie;
381 struct pcie_port *pp;
382 struct resource *res;
383 void __iomem *reg_p;
384 struct phy *phy;
385 int ret;
386
387 ks_pcie = devm_kzalloc(dev, sizeof(*ks_pcie), GFP_KERNEL);
388 if (!ks_pcie)
389 return -ENOMEM;
390
391 pp = &ks_pcie->pp;
392 pp->dev = dev;
393
394 /* initialize SerDes Phy if present */
395 phy = devm_phy_get(dev, "pcie-phy");
396 if (PTR_ERR_OR_ZERO(phy) == -EPROBE_DEFER)
397 return PTR_ERR(phy);
398
399 if (!IS_ERR_OR_NULL(phy)) {
400 ret = phy_init(phy);
401 if (ret < 0)
402 return ret;
403 }
404
405 /* index 2 is to read PCI DEVICE_ID */
406 res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
407 reg_p = devm_ioremap_resource(dev, res);
408 if (IS_ERR(reg_p))
409 return PTR_ERR(reg_p);
410 ks_pcie->device_id = readl(reg_p) >> 16;
411 devm_iounmap(dev, reg_p);
412 devm_release_mem_region(dev, res->start, resource_size(res));
413
414 ks_pcie->np = dev->of_node;
415 platform_set_drvdata(pdev, ks_pcie);
416 ks_pcie->clk = devm_clk_get(dev, "pcie");
417 if (IS_ERR(ks_pcie->clk)) {
418 dev_err(dev, "Failed to get pcie rc clock\n");
419 return PTR_ERR(ks_pcie->clk);
420 }
421 ret = clk_prepare_enable(ks_pcie->clk);
422 if (ret)
423 return ret;
424
425 ret = ks_add_pcie_port(ks_pcie, pdev);
426 if (ret < 0)
427 goto fail_clk;
428
429 return 0;
430fail_clk:
431 clk_disable_unprepare(ks_pcie->clk);
432
433 return ret;
434}
435
436static struct platform_driver ks_pcie_driver __refdata = {
437 .probe = ks_pcie_probe,
438 .remove = __exit_p(ks_pcie_remove),
439 .driver = {
440 .name = "keystone-pcie",
441 .of_match_table = of_match_ptr(ks_pcie_of_match),
442 },
443};
444builtin_platform_driver(ks_pcie_driver);