1 // SPDX-License-Identifier: GPL-2.0
3 * PCIe controller EP driver for Freescale Layerscape SoCs
5 * Copyright (C) 2018 NXP Semiconductor.
7 * Author: Xiaowei Bao <xiaowei.bao@nxp.com>
10 #include <linux/kernel.h>
11 #include <linux/init.h>
12 #include <linux/of_pci.h>
13 #include <linux/of_platform.h>
14 #include <linux/of_address.h>
15 #include <linux/pci.h>
16 #include <linux/platform_device.h>
17 #include <linux/resource.h>
19 #include "pcie-designware.h"
21 #define PEX_PF0_CONFIG 0xC0014
22 #define PEX_PF0_CFG_READY BIT(0)
24 /* PEX PFa PCIE PME and message interrupt registers*/
25 #define PEX_PF0_PME_MES_DR 0xC0020
26 #define PEX_PF0_PME_MES_DR_LUD BIT(7)
27 #define PEX_PF0_PME_MES_DR_LDD BIT(9)
28 #define PEX_PF0_PME_MES_DR_HRD BIT(10)
30 #define PEX_PF0_PME_MES_IER 0xC0028
31 #define PEX_PF0_PME_MES_IER_LUDIE BIT(7)
32 #define PEX_PF0_PME_MES_IER_LDDIE BIT(9)
33 #define PEX_PF0_PME_MES_IER_HRDIE BIT(10)
35 #define to_ls_pcie_ep(x) dev_get_drvdata((x)->dev)
37 struct ls_pcie_ep_drvdata
{
39 const struct dw_pcie_ep_ops
*ops
;
40 const struct dw_pcie_ops
*dw_pcie_ops
;
45 struct pci_epc_features
*ls_epc
;
46 const struct ls_pcie_ep_drvdata
*drvdata
;
52 static u32
ls_pcie_pf_lut_readl(struct ls_pcie_ep
*pcie
, u32 offset
)
54 struct dw_pcie
*pci
= pcie
->pci
;
57 return ioread32be(pci
->dbi_base
+ offset
);
59 return ioread32(pci
->dbi_base
+ offset
);
62 static void ls_pcie_pf_lut_writel(struct ls_pcie_ep
*pcie
, u32 offset
, u32 value
)
64 struct dw_pcie
*pci
= pcie
->pci
;
67 iowrite32be(value
, pci
->dbi_base
+ offset
);
69 iowrite32(value
, pci
->dbi_base
+ offset
);
72 static irqreturn_t
ls_pcie_ep_event_handler(int irq
, void *dev_id
)
74 struct ls_pcie_ep
*pcie
= dev_id
;
75 struct dw_pcie
*pci
= pcie
->pci
;
79 val
= ls_pcie_pf_lut_readl(pcie
, PEX_PF0_PME_MES_DR
);
80 ls_pcie_pf_lut_writel(pcie
, PEX_PF0_PME_MES_DR
, val
);
85 if (val
& PEX_PF0_PME_MES_DR_LUD
) {
87 offset
= dw_pcie_find_capability(pci
, PCI_CAP_ID_EXP
);
90 * The values of the Maximum Link Width and Supported Link
91 * Speed from the Link Capabilities Register will be lost
92 * during link down or hot reset. Restore initial value
93 * that configured by the Reset Configuration Word (RCW).
95 dw_pcie_dbi_ro_wr_en(pci
);
96 dw_pcie_writel_dbi(pci
, offset
+ PCI_EXP_LNKCAP
, pcie
->lnkcap
);
97 dw_pcie_dbi_ro_wr_dis(pci
);
99 cfg
= ls_pcie_pf_lut_readl(pcie
, PEX_PF0_CONFIG
);
100 cfg
|= PEX_PF0_CFG_READY
;
101 ls_pcie_pf_lut_writel(pcie
, PEX_PF0_CONFIG
, cfg
);
102 dw_pcie_ep_linkup(&pci
->ep
);
104 dev_dbg(pci
->dev
, "Link up\n");
105 } else if (val
& PEX_PF0_PME_MES_DR_LDD
) {
106 dev_dbg(pci
->dev
, "Link down\n");
107 dw_pcie_ep_linkdown(&pci
->ep
);
108 } else if (val
& PEX_PF0_PME_MES_DR_HRD
) {
109 dev_dbg(pci
->dev
, "Hot reset\n");
115 static int ls_pcie_ep_interrupt_init(struct ls_pcie_ep
*pcie
,
116 struct platform_device
*pdev
)
121 pcie
->irq
= platform_get_irq_byname(pdev
, "pme");
125 ret
= devm_request_irq(&pdev
->dev
, pcie
->irq
, ls_pcie_ep_event_handler
,
126 IRQF_SHARED
, pdev
->name
, pcie
);
128 dev_err(&pdev
->dev
, "Can't register PCIe IRQ\n");
132 /* Enable interrupts */
133 val
= ls_pcie_pf_lut_readl(pcie
, PEX_PF0_PME_MES_IER
);
134 val
|= PEX_PF0_PME_MES_IER_LDDIE
| PEX_PF0_PME_MES_IER_HRDIE
|
135 PEX_PF0_PME_MES_IER_LUDIE
;
136 ls_pcie_pf_lut_writel(pcie
, PEX_PF0_PME_MES_IER
, val
);
141 static const struct pci_epc_features
*
142 ls_pcie_ep_get_features(struct dw_pcie_ep
*ep
)
144 struct dw_pcie
*pci
= to_dw_pcie_from_ep(ep
);
145 struct ls_pcie_ep
*pcie
= to_ls_pcie_ep(pci
);
150 static void ls_pcie_ep_init(struct dw_pcie_ep
*ep
)
152 struct dw_pcie
*pci
= to_dw_pcie_from_ep(ep
);
153 struct ls_pcie_ep
*pcie
= to_ls_pcie_ep(pci
);
154 struct dw_pcie_ep_func
*ep_func
;
157 ep_func
= dw_pcie_ep_get_func_from_ep(ep
, 0);
161 for (bar
= 0; bar
< PCI_STD_NUM_BARS
; bar
++)
162 dw_pcie_ep_reset_bar(pci
, bar
);
164 pcie
->ls_epc
->msi_capable
= ep_func
->msi_cap
? true : false;
165 pcie
->ls_epc
->msix_capable
= ep_func
->msix_cap
? true : false;
168 static int ls_pcie_ep_raise_irq(struct dw_pcie_ep
*ep
, u8 func_no
,
169 unsigned int type
, u16 interrupt_num
)
171 struct dw_pcie
*pci
= to_dw_pcie_from_ep(ep
);
175 return dw_pcie_ep_raise_intx_irq(ep
, func_no
);
177 return dw_pcie_ep_raise_msi_irq(ep
, func_no
, interrupt_num
);
179 return dw_pcie_ep_raise_msix_irq_doorbell(ep
, func_no
,
182 dev_err(pci
->dev
, "UNKNOWN IRQ type\n");
187 static unsigned int ls_pcie_ep_get_dbi_offset(struct dw_pcie_ep
*ep
, u8 func_no
)
189 struct dw_pcie
*pci
= to_dw_pcie_from_ep(ep
);
190 struct ls_pcie_ep
*pcie
= to_ls_pcie_ep(pci
);
192 WARN_ON(func_no
&& !pcie
->drvdata
->func_offset
);
193 return pcie
->drvdata
->func_offset
* func_no
;
196 static const struct dw_pcie_ep_ops ls_pcie_ep_ops
= {
197 .init
= ls_pcie_ep_init
,
198 .raise_irq
= ls_pcie_ep_raise_irq
,
199 .get_features
= ls_pcie_ep_get_features
,
200 .get_dbi_offset
= ls_pcie_ep_get_dbi_offset
,
203 static const struct ls_pcie_ep_drvdata ls1_ep_drvdata
= {
204 .ops
= &ls_pcie_ep_ops
,
207 static const struct ls_pcie_ep_drvdata ls2_ep_drvdata
= {
208 .func_offset
= 0x20000,
209 .ops
= &ls_pcie_ep_ops
,
212 static const struct ls_pcie_ep_drvdata lx2_ep_drvdata
= {
213 .func_offset
= 0x8000,
214 .ops
= &ls_pcie_ep_ops
,
217 static const struct of_device_id ls_pcie_ep_of_match
[] = {
218 { .compatible
= "fsl,ls1028a-pcie-ep", .data
= &ls1_ep_drvdata
},
219 { .compatible
= "fsl,ls1046a-pcie-ep", .data
= &ls1_ep_drvdata
},
220 { .compatible
= "fsl,ls1088a-pcie-ep", .data
= &ls2_ep_drvdata
},
221 { .compatible
= "fsl,ls2088a-pcie-ep", .data
= &ls2_ep_drvdata
},
222 { .compatible
= "fsl,lx2160ar2-pcie-ep", .data
= &lx2_ep_drvdata
},
226 static int __init
ls_pcie_ep_probe(struct platform_device
*pdev
)
228 struct device
*dev
= &pdev
->dev
;
230 struct ls_pcie_ep
*pcie
;
231 struct pci_epc_features
*ls_epc
;
232 struct resource
*dbi_base
;
236 pcie
= devm_kzalloc(dev
, sizeof(*pcie
), GFP_KERNEL
);
240 pci
= devm_kzalloc(dev
, sizeof(*pci
), GFP_KERNEL
);
244 ls_epc
= devm_kzalloc(dev
, sizeof(*ls_epc
), GFP_KERNEL
);
248 pcie
->drvdata
= of_device_get_match_data(dev
);
251 pci
->ops
= pcie
->drvdata
->dw_pcie_ops
;
253 ls_epc
->bar
[BAR_2
].only_64bit
= true;
254 ls_epc
->bar
[BAR_3
].type
= BAR_RESERVED
;
255 ls_epc
->bar
[BAR_4
].only_64bit
= true;
256 ls_epc
->bar
[BAR_5
].type
= BAR_RESERVED
;
257 ls_epc
->linkup_notifier
= true;
260 pcie
->ls_epc
= ls_epc
;
262 dbi_base
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
, "regs");
263 pci
->dbi_base
= devm_pci_remap_cfg_resource(dev
, dbi_base
);
264 if (IS_ERR(pci
->dbi_base
))
265 return PTR_ERR(pci
->dbi_base
);
267 pci
->ep
.ops
= &ls_pcie_ep_ops
;
269 pcie
->big_endian
= of_property_read_bool(dev
->of_node
, "big-endian");
271 dma_set_mask_and_coherent(dev
, DMA_BIT_MASK(64));
273 platform_set_drvdata(pdev
, pcie
);
275 offset
= dw_pcie_find_capability(pci
, PCI_CAP_ID_EXP
);
276 pcie
->lnkcap
= dw_pcie_readl_dbi(pci
, offset
+ PCI_EXP_LNKCAP
);
278 ret
= dw_pcie_ep_init(&pci
->ep
);
282 ret
= dw_pcie_ep_init_registers(&pci
->ep
);
284 dev_err(dev
, "Failed to initialize DWC endpoint registers\n");
285 dw_pcie_ep_deinit(&pci
->ep
);
289 pci_epc_init_notify(pci
->ep
.epc
);
291 return ls_pcie_ep_interrupt_init(pcie
, pdev
);
294 static struct platform_driver ls_pcie_ep_driver
= {
296 .name
= "layerscape-pcie-ep",
297 .of_match_table
= ls_pcie_ep_of_match
,
298 .suppress_bind_attrs
= true,
301 builtin_platform_driver_probe(ls_pcie_ep_driver
, ls_pcie_ep_probe
);