1508f6106SBharat Kumar Gogada // SPDX-License-Identifier: GPL-2.0+
2508f6106SBharat Kumar Gogada /*
3508f6106SBharat Kumar Gogada * PCIe host controller driver for Xilinx Versal CPM DMA Bridge
4508f6106SBharat Kumar Gogada *
5508f6106SBharat Kumar Gogada * (C) Copyright 2019 - 2020, Xilinx, Inc.
6508f6106SBharat Kumar Gogada */
7508f6106SBharat Kumar Gogada
8508f6106SBharat Kumar Gogada #include <linux/bitfield.h>
9508f6106SBharat Kumar Gogada #include <linux/interrupt.h>
10508f6106SBharat Kumar Gogada #include <linux/irq.h>
11508f6106SBharat Kumar Gogada #include <linux/irqchip.h>
12508f6106SBharat Kumar Gogada #include <linux/irqchip/chained_irq.h>
13508f6106SBharat Kumar Gogada #include <linux/irqdomain.h>
14508f6106SBharat Kumar Gogada #include <linux/kernel.h>
15508f6106SBharat Kumar Gogada #include <linux/module.h>
16508f6106SBharat Kumar Gogada #include <linux/of_address.h>
17508f6106SBharat Kumar Gogada #include <linux/of_pci.h>
18508f6106SBharat Kumar Gogada #include <linux/of_platform.h>
19508f6106SBharat Kumar Gogada
20508f6106SBharat Kumar Gogada #include "../pci.h"
21*a977ee94SThippeswamy Havalige #include "pcie-xilinx-common.h"
22508f6106SBharat Kumar Gogada
23508f6106SBharat Kumar Gogada /* Register definitions */
24508f6106SBharat Kumar Gogada #define XILINX_CPM_PCIE_REG_IDR 0x00000E10
25508f6106SBharat Kumar Gogada #define XILINX_CPM_PCIE_REG_IMR 0x00000E14
26508f6106SBharat Kumar Gogada #define XILINX_CPM_PCIE_REG_PSCR 0x00000E1C
27508f6106SBharat Kumar Gogada #define XILINX_CPM_PCIE_REG_RPSC 0x00000E20
28508f6106SBharat Kumar Gogada #define XILINX_CPM_PCIE_REG_RPEFR 0x00000E2C
29508f6106SBharat Kumar Gogada #define XILINX_CPM_PCIE_REG_IDRN 0x00000E38
30508f6106SBharat Kumar Gogada #define XILINX_CPM_PCIE_REG_IDRN_MASK 0x00000E3C
31508f6106SBharat Kumar Gogada #define XILINX_CPM_PCIE_MISC_IR_STATUS 0x00000340
32508f6106SBharat Kumar Gogada #define XILINX_CPM_PCIE_MISC_IR_ENABLE 0x00000348
33508f6106SBharat Kumar Gogada #define XILINX_CPM_PCIE_MISC_IR_LOCAL BIT(1)
34508f6106SBharat Kumar Gogada
3551f1ffc0SBharat Kumar Gogada #define XILINX_CPM_PCIE_IR_STATUS 0x000002A0
3651f1ffc0SBharat Kumar Gogada #define XILINX_CPM_PCIE_IR_ENABLE 0x000002A8
3751f1ffc0SBharat Kumar Gogada #define XILINX_CPM_PCIE_IR_LOCAL BIT(0)
3851f1ffc0SBharat Kumar Gogada
39*a977ee94SThippeswamy Havalige #define IMR(x) BIT(XILINX_PCIE_INTR_ ##x)
40508f6106SBharat Kumar Gogada
41508f6106SBharat Kumar Gogada #define XILINX_CPM_PCIE_IMR_ALL_MASK \
42508f6106SBharat Kumar Gogada ( \
43508f6106SBharat Kumar Gogada IMR(LINK_DOWN) | \
44508f6106SBharat Kumar Gogada IMR(HOT_RESET) | \
45508f6106SBharat Kumar Gogada IMR(CFG_PCIE_TIMEOUT) | \
46508f6106SBharat Kumar Gogada IMR(CFG_TIMEOUT) | \
47508f6106SBharat Kumar Gogada IMR(CORRECTABLE) | \
48508f6106SBharat Kumar Gogada IMR(NONFATAL) | \
49508f6106SBharat Kumar Gogada IMR(FATAL) | \
50508f6106SBharat Kumar Gogada IMR(CFG_ERR_POISON) | \
51508f6106SBharat Kumar Gogada IMR(PME_TO_ACK_RCVD) | \
52508f6106SBharat Kumar Gogada IMR(INTX) | \
53508f6106SBharat Kumar Gogada IMR(PM_PME_RCVD) | \
54508f6106SBharat Kumar Gogada IMR(SLV_UNSUPP) | \
55508f6106SBharat Kumar Gogada IMR(SLV_UNEXP) | \
56508f6106SBharat Kumar Gogada IMR(SLV_COMPL) | \
57508f6106SBharat Kumar Gogada IMR(SLV_ERRP) | \
58508f6106SBharat Kumar Gogada IMR(SLV_CMPABT) | \
59508f6106SBharat Kumar Gogada IMR(SLV_ILLBUR) | \
60508f6106SBharat Kumar Gogada IMR(MST_DECERR) | \
61508f6106SBharat Kumar Gogada IMR(MST_SLVERR) | \
62508f6106SBharat Kumar Gogada IMR(SLV_PCIE_TIMEOUT) \
63508f6106SBharat Kumar Gogada )
64508f6106SBharat Kumar Gogada
65508f6106SBharat Kumar Gogada #define XILINX_CPM_PCIE_IDR_ALL_MASK 0xFFFFFFFF
66508f6106SBharat Kumar Gogada #define XILINX_CPM_PCIE_IDRN_MASK GENMASK(19, 16)
67508f6106SBharat Kumar Gogada #define XILINX_CPM_PCIE_IDRN_SHIFT 16
68508f6106SBharat Kumar Gogada
69508f6106SBharat Kumar Gogada /* Root Port Error FIFO Read Register definitions */
70508f6106SBharat Kumar Gogada #define XILINX_CPM_PCIE_RPEFR_ERR_VALID BIT(18)
71508f6106SBharat Kumar Gogada #define XILINX_CPM_PCIE_RPEFR_REQ_ID GENMASK(15, 0)
72508f6106SBharat Kumar Gogada #define XILINX_CPM_PCIE_RPEFR_ALL_MASK 0xFFFFFFFF
73508f6106SBharat Kumar Gogada
74508f6106SBharat Kumar Gogada /* Root Port Status/control Register definitions */
75508f6106SBharat Kumar Gogada #define XILINX_CPM_PCIE_REG_RPSC_BEN BIT(0)
76508f6106SBharat Kumar Gogada
77508f6106SBharat Kumar Gogada /* Phy Status/Control Register definitions */
78508f6106SBharat Kumar Gogada #define XILINX_CPM_PCIE_REG_PSCR_LNKUP BIT(11)
79508f6106SBharat Kumar Gogada
8051f1ffc0SBharat Kumar Gogada enum xilinx_cpm_version {
8151f1ffc0SBharat Kumar Gogada CPM,
8251f1ffc0SBharat Kumar Gogada CPM5,
8351f1ffc0SBharat Kumar Gogada };
8451f1ffc0SBharat Kumar Gogada
8551f1ffc0SBharat Kumar Gogada /**
8651f1ffc0SBharat Kumar Gogada * struct xilinx_cpm_variant - CPM variant information
8751f1ffc0SBharat Kumar Gogada * @version: CPM version
8851f1ffc0SBharat Kumar Gogada */
8951f1ffc0SBharat Kumar Gogada struct xilinx_cpm_variant {
9051f1ffc0SBharat Kumar Gogada enum xilinx_cpm_version version;
9151f1ffc0SBharat Kumar Gogada };
9251f1ffc0SBharat Kumar Gogada
93508f6106SBharat Kumar Gogada /**
94dacee587SBjorn Helgaas * struct xilinx_cpm_pcie - PCIe port information
95dacee587SBjorn Helgaas * @dev: Device pointer
96508f6106SBharat Kumar Gogada * @reg_base: Bridge Register Base
97508f6106SBharat Kumar Gogada * @cpm_base: CPM System Level Control and Status Register(SLCR) Base
98508f6106SBharat Kumar Gogada * @intx_domain: Legacy IRQ domain pointer
99508f6106SBharat Kumar Gogada * @cpm_domain: CPM IRQ domain pointer
100508f6106SBharat Kumar Gogada * @cfg: Holds mappings of config space window
101508f6106SBharat Kumar Gogada * @intx_irq: legacy interrupt number
102508f6106SBharat Kumar Gogada * @irq: Error interrupt number
103508f6106SBharat Kumar Gogada * @lock: lock protecting shared register access
10451f1ffc0SBharat Kumar Gogada * @variant: CPM version check pointer
105508f6106SBharat Kumar Gogada */
106dacee587SBjorn Helgaas struct xilinx_cpm_pcie {
107dacee587SBjorn Helgaas struct device *dev;
108508f6106SBharat Kumar Gogada void __iomem *reg_base;
109508f6106SBharat Kumar Gogada void __iomem *cpm_base;
110508f6106SBharat Kumar Gogada struct irq_domain *intx_domain;
111508f6106SBharat Kumar Gogada struct irq_domain *cpm_domain;
112508f6106SBharat Kumar Gogada struct pci_config_window *cfg;
113508f6106SBharat Kumar Gogada int intx_irq;
114508f6106SBharat Kumar Gogada int irq;
115508f6106SBharat Kumar Gogada raw_spinlock_t lock;
11651f1ffc0SBharat Kumar Gogada const struct xilinx_cpm_variant *variant;
117508f6106SBharat Kumar Gogada };
118508f6106SBharat Kumar Gogada
pcie_read(struct xilinx_cpm_pcie * port,u32 reg)119dacee587SBjorn Helgaas static u32 pcie_read(struct xilinx_cpm_pcie *port, u32 reg)
120508f6106SBharat Kumar Gogada {
121508f6106SBharat Kumar Gogada return readl_relaxed(port->reg_base + reg);
122508f6106SBharat Kumar Gogada }
123508f6106SBharat Kumar Gogada
pcie_write(struct xilinx_cpm_pcie * port,u32 val,u32 reg)124dacee587SBjorn Helgaas static void pcie_write(struct xilinx_cpm_pcie *port,
125508f6106SBharat Kumar Gogada u32 val, u32 reg)
126508f6106SBharat Kumar Gogada {
127508f6106SBharat Kumar Gogada writel_relaxed(val, port->reg_base + reg);
128508f6106SBharat Kumar Gogada }
129508f6106SBharat Kumar Gogada
cpm_pcie_link_up(struct xilinx_cpm_pcie * port)130dacee587SBjorn Helgaas static bool cpm_pcie_link_up(struct xilinx_cpm_pcie *port)
131508f6106SBharat Kumar Gogada {
132508f6106SBharat Kumar Gogada return (pcie_read(port, XILINX_CPM_PCIE_REG_PSCR) &
133508f6106SBharat Kumar Gogada XILINX_CPM_PCIE_REG_PSCR_LNKUP);
134508f6106SBharat Kumar Gogada }
135508f6106SBharat Kumar Gogada
cpm_pcie_clear_err_interrupts(struct xilinx_cpm_pcie * port)136dacee587SBjorn Helgaas static void cpm_pcie_clear_err_interrupts(struct xilinx_cpm_pcie *port)
137508f6106SBharat Kumar Gogada {
138508f6106SBharat Kumar Gogada unsigned long val = pcie_read(port, XILINX_CPM_PCIE_REG_RPEFR);
139508f6106SBharat Kumar Gogada
140508f6106SBharat Kumar Gogada if (val & XILINX_CPM_PCIE_RPEFR_ERR_VALID) {
141508f6106SBharat Kumar Gogada dev_dbg(port->dev, "Requester ID %lu\n",
142508f6106SBharat Kumar Gogada val & XILINX_CPM_PCIE_RPEFR_REQ_ID);
143508f6106SBharat Kumar Gogada pcie_write(port, XILINX_CPM_PCIE_RPEFR_ALL_MASK,
144508f6106SBharat Kumar Gogada XILINX_CPM_PCIE_REG_RPEFR);
145508f6106SBharat Kumar Gogada }
146508f6106SBharat Kumar Gogada }
147508f6106SBharat Kumar Gogada
xilinx_cpm_mask_leg_irq(struct irq_data * data)148508f6106SBharat Kumar Gogada static void xilinx_cpm_mask_leg_irq(struct irq_data *data)
149508f6106SBharat Kumar Gogada {
150dacee587SBjorn Helgaas struct xilinx_cpm_pcie *port = irq_data_get_irq_chip_data(data);
151508f6106SBharat Kumar Gogada unsigned long flags;
152508f6106SBharat Kumar Gogada u32 mask;
153508f6106SBharat Kumar Gogada u32 val;
154508f6106SBharat Kumar Gogada
155508f6106SBharat Kumar Gogada mask = BIT(data->hwirq + XILINX_CPM_PCIE_IDRN_SHIFT);
156508f6106SBharat Kumar Gogada raw_spin_lock_irqsave(&port->lock, flags);
157508f6106SBharat Kumar Gogada val = pcie_read(port, XILINX_CPM_PCIE_REG_IDRN_MASK);
158508f6106SBharat Kumar Gogada pcie_write(port, (val & (~mask)), XILINX_CPM_PCIE_REG_IDRN_MASK);
159508f6106SBharat Kumar Gogada raw_spin_unlock_irqrestore(&port->lock, flags);
160508f6106SBharat Kumar Gogada }
161508f6106SBharat Kumar Gogada
xilinx_cpm_unmask_leg_irq(struct irq_data * data)162508f6106SBharat Kumar Gogada static void xilinx_cpm_unmask_leg_irq(struct irq_data *data)
163508f6106SBharat Kumar Gogada {
164dacee587SBjorn Helgaas struct xilinx_cpm_pcie *port = irq_data_get_irq_chip_data(data);
165508f6106SBharat Kumar Gogada unsigned long flags;
166508f6106SBharat Kumar Gogada u32 mask;
167508f6106SBharat Kumar Gogada u32 val;
168508f6106SBharat Kumar Gogada
169508f6106SBharat Kumar Gogada mask = BIT(data->hwirq + XILINX_CPM_PCIE_IDRN_SHIFT);
170508f6106SBharat Kumar Gogada raw_spin_lock_irqsave(&port->lock, flags);
171508f6106SBharat Kumar Gogada val = pcie_read(port, XILINX_CPM_PCIE_REG_IDRN_MASK);
172508f6106SBharat Kumar Gogada pcie_write(port, (val | mask), XILINX_CPM_PCIE_REG_IDRN_MASK);
173508f6106SBharat Kumar Gogada raw_spin_unlock_irqrestore(&port->lock, flags);
174508f6106SBharat Kumar Gogada }
175508f6106SBharat Kumar Gogada
176508f6106SBharat Kumar Gogada static struct irq_chip xilinx_cpm_leg_irq_chip = {
177508f6106SBharat Kumar Gogada .name = "INTx",
178508f6106SBharat Kumar Gogada .irq_mask = xilinx_cpm_mask_leg_irq,
179508f6106SBharat Kumar Gogada .irq_unmask = xilinx_cpm_unmask_leg_irq,
180508f6106SBharat Kumar Gogada };
181508f6106SBharat Kumar Gogada
182508f6106SBharat Kumar Gogada /**
183508f6106SBharat Kumar Gogada * xilinx_cpm_pcie_intx_map - Set the handler for the INTx and mark IRQ as valid
184508f6106SBharat Kumar Gogada * @domain: IRQ domain
185508f6106SBharat Kumar Gogada * @irq: Virtual IRQ number
186508f6106SBharat Kumar Gogada * @hwirq: HW interrupt number
187508f6106SBharat Kumar Gogada *
188508f6106SBharat Kumar Gogada * Return: Always returns 0.
189508f6106SBharat Kumar Gogada */
xilinx_cpm_pcie_intx_map(struct irq_domain * domain,unsigned int irq,irq_hw_number_t hwirq)190508f6106SBharat Kumar Gogada static int xilinx_cpm_pcie_intx_map(struct irq_domain *domain,
191508f6106SBharat Kumar Gogada unsigned int irq, irq_hw_number_t hwirq)
192508f6106SBharat Kumar Gogada {
193508f6106SBharat Kumar Gogada irq_set_chip_and_handler(irq, &xilinx_cpm_leg_irq_chip,
194508f6106SBharat Kumar Gogada handle_level_irq);
195508f6106SBharat Kumar Gogada irq_set_chip_data(irq, domain->host_data);
196508f6106SBharat Kumar Gogada irq_set_status_flags(irq, IRQ_LEVEL);
197508f6106SBharat Kumar Gogada
198508f6106SBharat Kumar Gogada return 0;
199508f6106SBharat Kumar Gogada }
200508f6106SBharat Kumar Gogada
201508f6106SBharat Kumar Gogada /* INTx IRQ Domain operations */
202508f6106SBharat Kumar Gogada static const struct irq_domain_ops intx_domain_ops = {
203508f6106SBharat Kumar Gogada .map = xilinx_cpm_pcie_intx_map,
204508f6106SBharat Kumar Gogada };
205508f6106SBharat Kumar Gogada
xilinx_cpm_pcie_intx_flow(struct irq_desc * desc)206508f6106SBharat Kumar Gogada static void xilinx_cpm_pcie_intx_flow(struct irq_desc *desc)
207508f6106SBharat Kumar Gogada {
208dacee587SBjorn Helgaas struct xilinx_cpm_pcie *port = irq_desc_get_handler_data(desc);
209508f6106SBharat Kumar Gogada struct irq_chip *chip = irq_desc_get_chip(desc);
210508f6106SBharat Kumar Gogada unsigned long val;
211508f6106SBharat Kumar Gogada int i;
212508f6106SBharat Kumar Gogada
213508f6106SBharat Kumar Gogada chained_irq_enter(chip, desc);
214508f6106SBharat Kumar Gogada
215508f6106SBharat Kumar Gogada val = FIELD_GET(XILINX_CPM_PCIE_IDRN_MASK,
216508f6106SBharat Kumar Gogada pcie_read(port, XILINX_CPM_PCIE_REG_IDRN));
217508f6106SBharat Kumar Gogada
218508f6106SBharat Kumar Gogada for_each_set_bit(i, &val, PCI_NUM_INTX)
219d21faba1SMarc Zyngier generic_handle_domain_irq(port->intx_domain, i);
220508f6106SBharat Kumar Gogada
221508f6106SBharat Kumar Gogada chained_irq_exit(chip, desc);
222508f6106SBharat Kumar Gogada }
223508f6106SBharat Kumar Gogada
xilinx_cpm_mask_event_irq(struct irq_data * d)224508f6106SBharat Kumar Gogada static void xilinx_cpm_mask_event_irq(struct irq_data *d)
225508f6106SBharat Kumar Gogada {
226dacee587SBjorn Helgaas struct xilinx_cpm_pcie *port = irq_data_get_irq_chip_data(d);
227508f6106SBharat Kumar Gogada u32 val;
228508f6106SBharat Kumar Gogada
229508f6106SBharat Kumar Gogada raw_spin_lock(&port->lock);
230508f6106SBharat Kumar Gogada val = pcie_read(port, XILINX_CPM_PCIE_REG_IMR);
231508f6106SBharat Kumar Gogada val &= ~BIT(d->hwirq);
232508f6106SBharat Kumar Gogada pcie_write(port, val, XILINX_CPM_PCIE_REG_IMR);
233508f6106SBharat Kumar Gogada raw_spin_unlock(&port->lock);
234508f6106SBharat Kumar Gogada }
235508f6106SBharat Kumar Gogada
xilinx_cpm_unmask_event_irq(struct irq_data * d)236508f6106SBharat Kumar Gogada static void xilinx_cpm_unmask_event_irq(struct irq_data *d)
237508f6106SBharat Kumar Gogada {
238dacee587SBjorn Helgaas struct xilinx_cpm_pcie *port = irq_data_get_irq_chip_data(d);
239508f6106SBharat Kumar Gogada u32 val;
240508f6106SBharat Kumar Gogada
241508f6106SBharat Kumar Gogada raw_spin_lock(&port->lock);
242508f6106SBharat Kumar Gogada val = pcie_read(port, XILINX_CPM_PCIE_REG_IMR);
243508f6106SBharat Kumar Gogada val |= BIT(d->hwirq);
244508f6106SBharat Kumar Gogada pcie_write(port, val, XILINX_CPM_PCIE_REG_IMR);
245508f6106SBharat Kumar Gogada raw_spin_unlock(&port->lock);
246508f6106SBharat Kumar Gogada }
247508f6106SBharat Kumar Gogada
248508f6106SBharat Kumar Gogada static struct irq_chip xilinx_cpm_event_irq_chip = {
249508f6106SBharat Kumar Gogada .name = "RC-Event",
250508f6106SBharat Kumar Gogada .irq_mask = xilinx_cpm_mask_event_irq,
251508f6106SBharat Kumar Gogada .irq_unmask = xilinx_cpm_unmask_event_irq,
252508f6106SBharat Kumar Gogada };
253508f6106SBharat Kumar Gogada
xilinx_cpm_pcie_event_map(struct irq_domain * domain,unsigned int irq,irq_hw_number_t hwirq)254508f6106SBharat Kumar Gogada static int xilinx_cpm_pcie_event_map(struct irq_domain *domain,
255508f6106SBharat Kumar Gogada unsigned int irq, irq_hw_number_t hwirq)
256508f6106SBharat Kumar Gogada {
257508f6106SBharat Kumar Gogada irq_set_chip_and_handler(irq, &xilinx_cpm_event_irq_chip,
258508f6106SBharat Kumar Gogada handle_level_irq);
259508f6106SBharat Kumar Gogada irq_set_chip_data(irq, domain->host_data);
260508f6106SBharat Kumar Gogada irq_set_status_flags(irq, IRQ_LEVEL);
261508f6106SBharat Kumar Gogada return 0;
262508f6106SBharat Kumar Gogada }
263508f6106SBharat Kumar Gogada
264508f6106SBharat Kumar Gogada static const struct irq_domain_ops event_domain_ops = {
265508f6106SBharat Kumar Gogada .map = xilinx_cpm_pcie_event_map,
266508f6106SBharat Kumar Gogada };
267508f6106SBharat Kumar Gogada
xilinx_cpm_pcie_event_flow(struct irq_desc * desc)268508f6106SBharat Kumar Gogada static void xilinx_cpm_pcie_event_flow(struct irq_desc *desc)
269508f6106SBharat Kumar Gogada {
270dacee587SBjorn Helgaas struct xilinx_cpm_pcie *port = irq_desc_get_handler_data(desc);
271508f6106SBharat Kumar Gogada struct irq_chip *chip = irq_desc_get_chip(desc);
272508f6106SBharat Kumar Gogada unsigned long val;
273508f6106SBharat Kumar Gogada int i;
274508f6106SBharat Kumar Gogada
275508f6106SBharat Kumar Gogada chained_irq_enter(chip, desc);
276508f6106SBharat Kumar Gogada val = pcie_read(port, XILINX_CPM_PCIE_REG_IDR);
277508f6106SBharat Kumar Gogada val &= pcie_read(port, XILINX_CPM_PCIE_REG_IMR);
278508f6106SBharat Kumar Gogada for_each_set_bit(i, &val, 32)
279d21faba1SMarc Zyngier generic_handle_domain_irq(port->cpm_domain, i);
280508f6106SBharat Kumar Gogada pcie_write(port, val, XILINX_CPM_PCIE_REG_IDR);
281508f6106SBharat Kumar Gogada
28251f1ffc0SBharat Kumar Gogada if (port->variant->version == CPM5) {
28351f1ffc0SBharat Kumar Gogada val = readl_relaxed(port->cpm_base + XILINX_CPM_PCIE_IR_STATUS);
28451f1ffc0SBharat Kumar Gogada if (val)
28551f1ffc0SBharat Kumar Gogada writel_relaxed(val, port->cpm_base +
28651f1ffc0SBharat Kumar Gogada XILINX_CPM_PCIE_IR_STATUS);
28751f1ffc0SBharat Kumar Gogada }
28851f1ffc0SBharat Kumar Gogada
289508f6106SBharat Kumar Gogada /*
290508f6106SBharat Kumar Gogada * XILINX_CPM_PCIE_MISC_IR_STATUS register is mapped to
291508f6106SBharat Kumar Gogada * CPM SLCR block.
292508f6106SBharat Kumar Gogada */
293508f6106SBharat Kumar Gogada val = readl_relaxed(port->cpm_base + XILINX_CPM_PCIE_MISC_IR_STATUS);
294508f6106SBharat Kumar Gogada if (val)
295508f6106SBharat Kumar Gogada writel_relaxed(val,
296508f6106SBharat Kumar Gogada port->cpm_base + XILINX_CPM_PCIE_MISC_IR_STATUS);
297508f6106SBharat Kumar Gogada
298508f6106SBharat Kumar Gogada chained_irq_exit(chip, desc);
299508f6106SBharat Kumar Gogada }
300508f6106SBharat Kumar Gogada
301508f6106SBharat Kumar Gogada #define _IC(x, s) \
302*a977ee94SThippeswamy Havalige [XILINX_PCIE_INTR_ ## x] = { __stringify(x), s }
303508f6106SBharat Kumar Gogada
304508f6106SBharat Kumar Gogada static const struct {
305508f6106SBharat Kumar Gogada const char *sym;
306508f6106SBharat Kumar Gogada const char *str;
307508f6106SBharat Kumar Gogada } intr_cause[32] = {
308508f6106SBharat Kumar Gogada _IC(LINK_DOWN, "Link Down"),
309508f6106SBharat Kumar Gogada _IC(HOT_RESET, "Hot reset"),
310508f6106SBharat Kumar Gogada _IC(CFG_TIMEOUT, "ECAM access timeout"),
311508f6106SBharat Kumar Gogada _IC(CORRECTABLE, "Correctable error message"),
312508f6106SBharat Kumar Gogada _IC(NONFATAL, "Non fatal error message"),
313508f6106SBharat Kumar Gogada _IC(FATAL, "Fatal error message"),
314508f6106SBharat Kumar Gogada _IC(SLV_UNSUPP, "Slave unsupported request"),
315508f6106SBharat Kumar Gogada _IC(SLV_UNEXP, "Slave unexpected completion"),
316508f6106SBharat Kumar Gogada _IC(SLV_COMPL, "Slave completion timeout"),
317508f6106SBharat Kumar Gogada _IC(SLV_ERRP, "Slave Error Poison"),
318508f6106SBharat Kumar Gogada _IC(SLV_CMPABT, "Slave Completer Abort"),
319508f6106SBharat Kumar Gogada _IC(SLV_ILLBUR, "Slave Illegal Burst"),
320508f6106SBharat Kumar Gogada _IC(MST_DECERR, "Master decode error"),
321508f6106SBharat Kumar Gogada _IC(MST_SLVERR, "Master slave error"),
322508f6106SBharat Kumar Gogada _IC(CFG_PCIE_TIMEOUT, "PCIe ECAM access timeout"),
323508f6106SBharat Kumar Gogada _IC(CFG_ERR_POISON, "ECAM poisoned completion received"),
324508f6106SBharat Kumar Gogada _IC(PME_TO_ACK_RCVD, "PME_TO_ACK message received"),
325508f6106SBharat Kumar Gogada _IC(PM_PME_RCVD, "PM_PME message received"),
326508f6106SBharat Kumar Gogada _IC(SLV_PCIE_TIMEOUT, "PCIe completion timeout received"),
327508f6106SBharat Kumar Gogada };
328508f6106SBharat Kumar Gogada
xilinx_cpm_pcie_intr_handler(int irq,void * dev_id)329508f6106SBharat Kumar Gogada static irqreturn_t xilinx_cpm_pcie_intr_handler(int irq, void *dev_id)
330508f6106SBharat Kumar Gogada {
331dacee587SBjorn Helgaas struct xilinx_cpm_pcie *port = dev_id;
332508f6106SBharat Kumar Gogada struct device *dev = port->dev;
333508f6106SBharat Kumar Gogada struct irq_data *d;
334508f6106SBharat Kumar Gogada
335508f6106SBharat Kumar Gogada d = irq_domain_get_irq_data(port->cpm_domain, irq);
336508f6106SBharat Kumar Gogada
337508f6106SBharat Kumar Gogada switch (d->hwirq) {
338*a977ee94SThippeswamy Havalige case XILINX_PCIE_INTR_CORRECTABLE:
339*a977ee94SThippeswamy Havalige case XILINX_PCIE_INTR_NONFATAL:
340*a977ee94SThippeswamy Havalige case XILINX_PCIE_INTR_FATAL:
341508f6106SBharat Kumar Gogada cpm_pcie_clear_err_interrupts(port);
342508f6106SBharat Kumar Gogada fallthrough;
343508f6106SBharat Kumar Gogada
344508f6106SBharat Kumar Gogada default:
345508f6106SBharat Kumar Gogada if (intr_cause[d->hwirq].str)
346508f6106SBharat Kumar Gogada dev_warn(dev, "%s\n", intr_cause[d->hwirq].str);
347508f6106SBharat Kumar Gogada else
348508f6106SBharat Kumar Gogada dev_warn(dev, "Unknown IRQ %ld\n", d->hwirq);
349508f6106SBharat Kumar Gogada }
350508f6106SBharat Kumar Gogada
351508f6106SBharat Kumar Gogada return IRQ_HANDLED;
352508f6106SBharat Kumar Gogada }
353508f6106SBharat Kumar Gogada
xilinx_cpm_free_irq_domains(struct xilinx_cpm_pcie * port)354dacee587SBjorn Helgaas static void xilinx_cpm_free_irq_domains(struct xilinx_cpm_pcie *port)
355508f6106SBharat Kumar Gogada {
356508f6106SBharat Kumar Gogada if (port->intx_domain) {
357508f6106SBharat Kumar Gogada irq_domain_remove(port->intx_domain);
358508f6106SBharat Kumar Gogada port->intx_domain = NULL;
359508f6106SBharat Kumar Gogada }
360508f6106SBharat Kumar Gogada
361508f6106SBharat Kumar Gogada if (port->cpm_domain) {
362508f6106SBharat Kumar Gogada irq_domain_remove(port->cpm_domain);
363508f6106SBharat Kumar Gogada port->cpm_domain = NULL;
364508f6106SBharat Kumar Gogada }
365508f6106SBharat Kumar Gogada }
366508f6106SBharat Kumar Gogada
367508f6106SBharat Kumar Gogada /**
368508f6106SBharat Kumar Gogada * xilinx_cpm_pcie_init_irq_domain - Initialize IRQ domain
369508f6106SBharat Kumar Gogada * @port: PCIe port information
370508f6106SBharat Kumar Gogada *
371508f6106SBharat Kumar Gogada * Return: '0' on success and error value on failure
372508f6106SBharat Kumar Gogada */
xilinx_cpm_pcie_init_irq_domain(struct xilinx_cpm_pcie * port)373dacee587SBjorn Helgaas static int xilinx_cpm_pcie_init_irq_domain(struct xilinx_cpm_pcie *port)
374508f6106SBharat Kumar Gogada {
375508f6106SBharat Kumar Gogada struct device *dev = port->dev;
376508f6106SBharat Kumar Gogada struct device_node *node = dev->of_node;
377508f6106SBharat Kumar Gogada struct device_node *pcie_intc_node;
378508f6106SBharat Kumar Gogada
379508f6106SBharat Kumar Gogada /* Setup INTx */
380508f6106SBharat Kumar Gogada pcie_intc_node = of_get_next_child(node, NULL);
381508f6106SBharat Kumar Gogada if (!pcie_intc_node) {
382508f6106SBharat Kumar Gogada dev_err(dev, "No PCIe Intc node found\n");
383508f6106SBharat Kumar Gogada return -EINVAL;
384508f6106SBharat Kumar Gogada }
385508f6106SBharat Kumar Gogada
386508f6106SBharat Kumar Gogada port->cpm_domain = irq_domain_add_linear(pcie_intc_node, 32,
387508f6106SBharat Kumar Gogada &event_domain_ops,
388508f6106SBharat Kumar Gogada port);
389508f6106SBharat Kumar Gogada if (!port->cpm_domain)
390508f6106SBharat Kumar Gogada goto out;
391508f6106SBharat Kumar Gogada
392508f6106SBharat Kumar Gogada irq_domain_update_bus_token(port->cpm_domain, DOMAIN_BUS_NEXUS);
393508f6106SBharat Kumar Gogada
394508f6106SBharat Kumar Gogada port->intx_domain = irq_domain_add_linear(pcie_intc_node, PCI_NUM_INTX,
395508f6106SBharat Kumar Gogada &intx_domain_ops,
396508f6106SBharat Kumar Gogada port);
397508f6106SBharat Kumar Gogada if (!port->intx_domain)
398508f6106SBharat Kumar Gogada goto out;
399508f6106SBharat Kumar Gogada
400508f6106SBharat Kumar Gogada irq_domain_update_bus_token(port->intx_domain, DOMAIN_BUS_WIRED);
401508f6106SBharat Kumar Gogada
402508f6106SBharat Kumar Gogada of_node_put(pcie_intc_node);
403508f6106SBharat Kumar Gogada raw_spin_lock_init(&port->lock);
404508f6106SBharat Kumar Gogada
405508f6106SBharat Kumar Gogada return 0;
406508f6106SBharat Kumar Gogada out:
407508f6106SBharat Kumar Gogada xilinx_cpm_free_irq_domains(port);
408ae191d2eSPan Bian of_node_put(pcie_intc_node);
409508f6106SBharat Kumar Gogada dev_err(dev, "Failed to allocate IRQ domains\n");
410508f6106SBharat Kumar Gogada
411508f6106SBharat Kumar Gogada return -ENOMEM;
412508f6106SBharat Kumar Gogada }
413508f6106SBharat Kumar Gogada
xilinx_cpm_setup_irq(struct xilinx_cpm_pcie * port)414dacee587SBjorn Helgaas static int xilinx_cpm_setup_irq(struct xilinx_cpm_pcie *port)
415508f6106SBharat Kumar Gogada {
416508f6106SBharat Kumar Gogada struct device *dev = port->dev;
417508f6106SBharat Kumar Gogada struct platform_device *pdev = to_platform_device(dev);
418508f6106SBharat Kumar Gogada int i, irq;
419508f6106SBharat Kumar Gogada
420508f6106SBharat Kumar Gogada port->irq = platform_get_irq(pdev, 0);
421508f6106SBharat Kumar Gogada if (port->irq < 0)
422508f6106SBharat Kumar Gogada return port->irq;
423508f6106SBharat Kumar Gogada
424508f6106SBharat Kumar Gogada for (i = 0; i < ARRAY_SIZE(intr_cause); i++) {
425508f6106SBharat Kumar Gogada int err;
426508f6106SBharat Kumar Gogada
427508f6106SBharat Kumar Gogada if (!intr_cause[i].str)
428508f6106SBharat Kumar Gogada continue;
429508f6106SBharat Kumar Gogada
430508f6106SBharat Kumar Gogada irq = irq_create_mapping(port->cpm_domain, i);
431508f6106SBharat Kumar Gogada if (!irq) {
432508f6106SBharat Kumar Gogada dev_err(dev, "Failed to map interrupt\n");
433508f6106SBharat Kumar Gogada return -ENXIO;
434508f6106SBharat Kumar Gogada }
435508f6106SBharat Kumar Gogada
436508f6106SBharat Kumar Gogada err = devm_request_irq(dev, irq, xilinx_cpm_pcie_intr_handler,
437508f6106SBharat Kumar Gogada 0, intr_cause[i].sym, port);
438508f6106SBharat Kumar Gogada if (err) {
439508f6106SBharat Kumar Gogada dev_err(dev, "Failed to request IRQ %d\n", irq);
440508f6106SBharat Kumar Gogada return err;
441508f6106SBharat Kumar Gogada }
442508f6106SBharat Kumar Gogada }
443508f6106SBharat Kumar Gogada
444508f6106SBharat Kumar Gogada port->intx_irq = irq_create_mapping(port->cpm_domain,
445*a977ee94SThippeswamy Havalige XILINX_PCIE_INTR_INTX);
446508f6106SBharat Kumar Gogada if (!port->intx_irq) {
447508f6106SBharat Kumar Gogada dev_err(dev, "Failed to map INTx interrupt\n");
448508f6106SBharat Kumar Gogada return -ENXIO;
449508f6106SBharat Kumar Gogada }
450508f6106SBharat Kumar Gogada
451508f6106SBharat Kumar Gogada /* Plug the INTx chained handler */
452508f6106SBharat Kumar Gogada irq_set_chained_handler_and_data(port->intx_irq,
453508f6106SBharat Kumar Gogada xilinx_cpm_pcie_intx_flow, port);
454508f6106SBharat Kumar Gogada
455508f6106SBharat Kumar Gogada /* Plug the main event chained handler */
456508f6106SBharat Kumar Gogada irq_set_chained_handler_and_data(port->irq,
457508f6106SBharat Kumar Gogada xilinx_cpm_pcie_event_flow, port);
458508f6106SBharat Kumar Gogada
459508f6106SBharat Kumar Gogada return 0;
460508f6106SBharat Kumar Gogada }
461508f6106SBharat Kumar Gogada
462508f6106SBharat Kumar Gogada /**
463508f6106SBharat Kumar Gogada * xilinx_cpm_pcie_init_port - Initialize hardware
464508f6106SBharat Kumar Gogada * @port: PCIe port information
465508f6106SBharat Kumar Gogada */
xilinx_cpm_pcie_init_port(struct xilinx_cpm_pcie * port)466dacee587SBjorn Helgaas static void xilinx_cpm_pcie_init_port(struct xilinx_cpm_pcie *port)
467508f6106SBharat Kumar Gogada {
468508f6106SBharat Kumar Gogada if (cpm_pcie_link_up(port))
469508f6106SBharat Kumar Gogada dev_info(port->dev, "PCIe Link is UP\n");
470508f6106SBharat Kumar Gogada else
471508f6106SBharat Kumar Gogada dev_info(port->dev, "PCIe Link is DOWN\n");
472508f6106SBharat Kumar Gogada
473508f6106SBharat Kumar Gogada /* Disable all interrupts */
474508f6106SBharat Kumar Gogada pcie_write(port, ~XILINX_CPM_PCIE_IDR_ALL_MASK,
475508f6106SBharat Kumar Gogada XILINX_CPM_PCIE_REG_IMR);
476508f6106SBharat Kumar Gogada
477508f6106SBharat Kumar Gogada /* Clear pending interrupts */
478508f6106SBharat Kumar Gogada pcie_write(port, pcie_read(port, XILINX_CPM_PCIE_REG_IDR) &
479508f6106SBharat Kumar Gogada XILINX_CPM_PCIE_IMR_ALL_MASK,
480508f6106SBharat Kumar Gogada XILINX_CPM_PCIE_REG_IDR);
481508f6106SBharat Kumar Gogada
482508f6106SBharat Kumar Gogada /*
483508f6106SBharat Kumar Gogada * XILINX_CPM_PCIE_MISC_IR_ENABLE register is mapped to
484508f6106SBharat Kumar Gogada * CPM SLCR block.
485508f6106SBharat Kumar Gogada */
486508f6106SBharat Kumar Gogada writel(XILINX_CPM_PCIE_MISC_IR_LOCAL,
487508f6106SBharat Kumar Gogada port->cpm_base + XILINX_CPM_PCIE_MISC_IR_ENABLE);
48851f1ffc0SBharat Kumar Gogada
48951f1ffc0SBharat Kumar Gogada if (port->variant->version == CPM5) {
49051f1ffc0SBharat Kumar Gogada writel(XILINX_CPM_PCIE_IR_LOCAL,
49151f1ffc0SBharat Kumar Gogada port->cpm_base + XILINX_CPM_PCIE_IR_ENABLE);
49251f1ffc0SBharat Kumar Gogada }
49351f1ffc0SBharat Kumar Gogada
494508f6106SBharat Kumar Gogada /* Enable the Bridge enable bit */
495508f6106SBharat Kumar Gogada pcie_write(port, pcie_read(port, XILINX_CPM_PCIE_REG_RPSC) |
496508f6106SBharat Kumar Gogada XILINX_CPM_PCIE_REG_RPSC_BEN,
497508f6106SBharat Kumar Gogada XILINX_CPM_PCIE_REG_RPSC);
498508f6106SBharat Kumar Gogada }
499508f6106SBharat Kumar Gogada
500508f6106SBharat Kumar Gogada /**
501508f6106SBharat Kumar Gogada * xilinx_cpm_pcie_parse_dt - Parse Device tree
502508f6106SBharat Kumar Gogada * @port: PCIe port information
503508f6106SBharat Kumar Gogada * @bus_range: Bus resource
504508f6106SBharat Kumar Gogada *
505508f6106SBharat Kumar Gogada * Return: '0' on success and error value on failure
506508f6106SBharat Kumar Gogada */
xilinx_cpm_pcie_parse_dt(struct xilinx_cpm_pcie * port,struct resource * bus_range)507dacee587SBjorn Helgaas static int xilinx_cpm_pcie_parse_dt(struct xilinx_cpm_pcie *port,
508508f6106SBharat Kumar Gogada struct resource *bus_range)
509508f6106SBharat Kumar Gogada {
510508f6106SBharat Kumar Gogada struct device *dev = port->dev;
511508f6106SBharat Kumar Gogada struct platform_device *pdev = to_platform_device(dev);
512508f6106SBharat Kumar Gogada struct resource *res;
513508f6106SBharat Kumar Gogada
514508f6106SBharat Kumar Gogada port->cpm_base = devm_platform_ioremap_resource_byname(pdev,
515508f6106SBharat Kumar Gogada "cpm_slcr");
516508f6106SBharat Kumar Gogada if (IS_ERR(port->cpm_base))
517508f6106SBharat Kumar Gogada return PTR_ERR(port->cpm_base);
518508f6106SBharat Kumar Gogada
519508f6106SBharat Kumar Gogada res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cfg");
520508f6106SBharat Kumar Gogada if (!res)
521508f6106SBharat Kumar Gogada return -ENXIO;
522508f6106SBharat Kumar Gogada
523508f6106SBharat Kumar Gogada port->cfg = pci_ecam_create(dev, res, bus_range,
524508f6106SBharat Kumar Gogada &pci_generic_ecam_ops);
525508f6106SBharat Kumar Gogada if (IS_ERR(port->cfg))
526508f6106SBharat Kumar Gogada return PTR_ERR(port->cfg);
527508f6106SBharat Kumar Gogada
52851f1ffc0SBharat Kumar Gogada if (port->variant->version == CPM5) {
52951f1ffc0SBharat Kumar Gogada port->reg_base = devm_platform_ioremap_resource_byname(pdev,
53051f1ffc0SBharat Kumar Gogada "cpm_csr");
53151f1ffc0SBharat Kumar Gogada if (IS_ERR(port->reg_base))
53251f1ffc0SBharat Kumar Gogada return PTR_ERR(port->reg_base);
53351f1ffc0SBharat Kumar Gogada } else {
534508f6106SBharat Kumar Gogada port->reg_base = port->cfg->win;
53551f1ffc0SBharat Kumar Gogada }
536508f6106SBharat Kumar Gogada
537508f6106SBharat Kumar Gogada return 0;
538508f6106SBharat Kumar Gogada }
539508f6106SBharat Kumar Gogada
xilinx_cpm_free_interrupts(struct xilinx_cpm_pcie * port)540dacee587SBjorn Helgaas static void xilinx_cpm_free_interrupts(struct xilinx_cpm_pcie *port)
541508f6106SBharat Kumar Gogada {
542508f6106SBharat Kumar Gogada irq_set_chained_handler_and_data(port->intx_irq, NULL, NULL);
543508f6106SBharat Kumar Gogada irq_set_chained_handler_and_data(port->irq, NULL, NULL);
544508f6106SBharat Kumar Gogada }
545508f6106SBharat Kumar Gogada
546508f6106SBharat Kumar Gogada /**
547508f6106SBharat Kumar Gogada * xilinx_cpm_pcie_probe - Probe function
548508f6106SBharat Kumar Gogada * @pdev: Platform device pointer
549508f6106SBharat Kumar Gogada *
550508f6106SBharat Kumar Gogada * Return: '0' on success and error value on failure
551508f6106SBharat Kumar Gogada */
xilinx_cpm_pcie_probe(struct platform_device * pdev)552508f6106SBharat Kumar Gogada static int xilinx_cpm_pcie_probe(struct platform_device *pdev)
553508f6106SBharat Kumar Gogada {
554dacee587SBjorn Helgaas struct xilinx_cpm_pcie *port;
555508f6106SBharat Kumar Gogada struct device *dev = &pdev->dev;
556508f6106SBharat Kumar Gogada struct pci_host_bridge *bridge;
55749e427e6SBjorn Helgaas struct resource_entry *bus;
558508f6106SBharat Kumar Gogada int err;
559508f6106SBharat Kumar Gogada
560508f6106SBharat Kumar Gogada bridge = devm_pci_alloc_host_bridge(dev, sizeof(*port));
561508f6106SBharat Kumar Gogada if (!bridge)
562508f6106SBharat Kumar Gogada return -ENODEV;
563508f6106SBharat Kumar Gogada
564508f6106SBharat Kumar Gogada port = pci_host_bridge_priv(bridge);
565508f6106SBharat Kumar Gogada
566508f6106SBharat Kumar Gogada port->dev = dev;
567508f6106SBharat Kumar Gogada
568508f6106SBharat Kumar Gogada err = xilinx_cpm_pcie_init_irq_domain(port);
569508f6106SBharat Kumar Gogada if (err)
570508f6106SBharat Kumar Gogada return err;
571508f6106SBharat Kumar Gogada
57249e427e6SBjorn Helgaas bus = resource_list_first_type(&bridge->windows, IORESOURCE_BUS);
57349e427e6SBjorn Helgaas if (!bus)
57449e427e6SBjorn Helgaas return -ENODEV;
57549e427e6SBjorn Helgaas
57651f1ffc0SBharat Kumar Gogada port->variant = of_device_get_match_data(dev);
57751f1ffc0SBharat Kumar Gogada
57849e427e6SBjorn Helgaas err = xilinx_cpm_pcie_parse_dt(port, bus->res);
579508f6106SBharat Kumar Gogada if (err) {
580508f6106SBharat Kumar Gogada dev_err(dev, "Parsing DT failed\n");
581508f6106SBharat Kumar Gogada goto err_parse_dt;
582508f6106SBharat Kumar Gogada }
583508f6106SBharat Kumar Gogada
584508f6106SBharat Kumar Gogada xilinx_cpm_pcie_init_port(port);
585508f6106SBharat Kumar Gogada
586508f6106SBharat Kumar Gogada err = xilinx_cpm_setup_irq(port);
587508f6106SBharat Kumar Gogada if (err) {
588508f6106SBharat Kumar Gogada dev_err(dev, "Failed to set up interrupts\n");
589508f6106SBharat Kumar Gogada goto err_setup_irq;
590508f6106SBharat Kumar Gogada }
591508f6106SBharat Kumar Gogada
592508f6106SBharat Kumar Gogada bridge->sysdata = port->cfg;
593508f6106SBharat Kumar Gogada bridge->ops = (struct pci_ops *)&pci_generic_ecam_ops.pci_ops;
594508f6106SBharat Kumar Gogada
595508f6106SBharat Kumar Gogada err = pci_host_probe(bridge);
596508f6106SBharat Kumar Gogada if (err < 0)
597508f6106SBharat Kumar Gogada goto err_host_bridge;
598508f6106SBharat Kumar Gogada
599508f6106SBharat Kumar Gogada return 0;
600508f6106SBharat Kumar Gogada
601508f6106SBharat Kumar Gogada err_host_bridge:
602508f6106SBharat Kumar Gogada xilinx_cpm_free_interrupts(port);
603508f6106SBharat Kumar Gogada err_setup_irq:
604508f6106SBharat Kumar Gogada pci_ecam_free(port->cfg);
605508f6106SBharat Kumar Gogada err_parse_dt:
606508f6106SBharat Kumar Gogada xilinx_cpm_free_irq_domains(port);
607508f6106SBharat Kumar Gogada return err;
608508f6106SBharat Kumar Gogada }
609508f6106SBharat Kumar Gogada
61051f1ffc0SBharat Kumar Gogada static const struct xilinx_cpm_variant cpm_host = {
61151f1ffc0SBharat Kumar Gogada .version = CPM,
61251f1ffc0SBharat Kumar Gogada };
61351f1ffc0SBharat Kumar Gogada
61451f1ffc0SBharat Kumar Gogada static const struct xilinx_cpm_variant cpm5_host = {
61551f1ffc0SBharat Kumar Gogada .version = CPM5,
61651f1ffc0SBharat Kumar Gogada };
61751f1ffc0SBharat Kumar Gogada
618508f6106SBharat Kumar Gogada static const struct of_device_id xilinx_cpm_pcie_of_match[] = {
61951f1ffc0SBharat Kumar Gogada {
62051f1ffc0SBharat Kumar Gogada .compatible = "xlnx,versal-cpm-host-1.00",
62151f1ffc0SBharat Kumar Gogada .data = &cpm_host,
62251f1ffc0SBharat Kumar Gogada },
62351f1ffc0SBharat Kumar Gogada {
62451f1ffc0SBharat Kumar Gogada .compatible = "xlnx,versal-cpm5-host",
62551f1ffc0SBharat Kumar Gogada .data = &cpm5_host,
62651f1ffc0SBharat Kumar Gogada },
627508f6106SBharat Kumar Gogada {}
628508f6106SBharat Kumar Gogada };
629508f6106SBharat Kumar Gogada
630508f6106SBharat Kumar Gogada static struct platform_driver xilinx_cpm_pcie_driver = {
631508f6106SBharat Kumar Gogada .driver = {
632508f6106SBharat Kumar Gogada .name = "xilinx-cpm-pcie",
633508f6106SBharat Kumar Gogada .of_match_table = xilinx_cpm_pcie_of_match,
634508f6106SBharat Kumar Gogada .suppress_bind_attrs = true,
635508f6106SBharat Kumar Gogada },
636508f6106SBharat Kumar Gogada .probe = xilinx_cpm_pcie_probe,
637508f6106SBharat Kumar Gogada };
638508f6106SBharat Kumar Gogada
639508f6106SBharat Kumar Gogada builtin_platform_driver(xilinx_cpm_pcie_driver);
640