1 // SPDX-License-Identifier: GPL-2.0
3 * PCIe host controller driver for Mobiveil PCIe Host controller
5 * Copyright (c) 2018 Mobiveil Inc.
6 * Author: Subrahmanya Lingappa <l.subrahmanya@mobiveil.co.in>
9 #include <linux/delay.h>
10 #include <linux/init.h>
11 #include <linux/interrupt.h>
12 #include <linux/irq.h>
13 #include <linux/irqchip/chained_irq.h>
14 #include <linux/irqdomain.h>
15 #include <linux/kernel.h>
16 #include <linux/module.h>
17 #include <linux/msi.h>
18 #include <linux/of_address.h>
19 #include <linux/of_irq.h>
20 #include <linux/of_platform.h>
21 #include <linux/of_pci.h>
22 #include <linux/pci.h>
23 #include <linux/platform_device.h>
24 #include <linux/slab.h>
26 /* register offsets and bit positions */
29 * translation tables are grouped into windows, each window registers are
30 * grouped into blocks of 4 or 16 registers each
32 #define PAB_REG_BLOCK_SIZE 16
33 #define PAB_EXT_REG_BLOCK_SIZE 4
35 #define PAB_REG_ADDR(offset, win) (offset + (win * PAB_REG_BLOCK_SIZE))
36 #define PAB_EXT_REG_ADDR(offset, win) (offset + (win * PAB_EXT_REG_BLOCK_SIZE))
38 #define LTSSM_STATUS 0x0404
39 #define LTSSM_STATUS_L0_MASK 0x3f
40 #define LTSSM_STATUS_L0 0x2d
42 #define PAB_CTRL 0x0808
43 #define AMBA_PIO_ENABLE_SHIFT 0
44 #define PEX_PIO_ENABLE_SHIFT 1
45 #define PAGE_SEL_SHIFT 13
46 #define PAGE_SEL_MASK 0x3f
47 #define PAGE_LO_MASK 0x3ff
48 #define PAGE_SEL_EN 0xc00
49 #define PAGE_SEL_OFFSET_SHIFT 10
51 #define PAB_AXI_PIO_CTRL 0x0840
52 #define APIO_EN_MASK 0xf
54 #define PAB_PEX_PIO_CTRL 0x08c0
55 #define PIO_ENABLE_SHIFT 0
57 #define PAB_INTP_AMBA_MISC_ENB 0x0b0c
58 #define PAB_INTP_AMBA_MISC_STAT 0x0b1c
59 #define PAB_INTP_INTX_MASK 0x01e0
60 #define PAB_INTP_MSI_MASK 0x8
62 #define PAB_AXI_AMAP_CTRL(win) PAB_REG_ADDR(0x0ba0, win)
63 #define WIN_ENABLE_SHIFT 0
64 #define WIN_TYPE_SHIFT 1
66 #define PAB_EXT_AXI_AMAP_SIZE(win) PAB_EXT_REG_ADDR(0xbaf0, win)
68 #define PAB_AXI_AMAP_AXI_WIN(win) PAB_REG_ADDR(0x0ba4, win)
69 #define AXI_WINDOW_ALIGN_MASK 3
71 #define PAB_AXI_AMAP_PEX_WIN_L(win) PAB_REG_ADDR(0x0ba8, win)
72 #define PAB_BUS_SHIFT 24
73 #define PAB_DEVICE_SHIFT 19
74 #define PAB_FUNCTION_SHIFT 16
76 #define PAB_AXI_AMAP_PEX_WIN_H(win) PAB_REG_ADDR(0x0bac, win)
77 #define PAB_INTP_AXI_PIO_CLASS 0x474
79 #define PAB_PEX_AMAP_CTRL(win) PAB_REG_ADDR(0x4ba0, win)
80 #define AMAP_CTRL_EN_SHIFT 0
81 #define AMAP_CTRL_TYPE_SHIFT 1
83 #define PAB_EXT_PEX_AMAP_SIZEN(win) PAB_EXT_REG_ADDR(0xbef0, win)
84 #define PAB_PEX_AMAP_AXI_WIN(win) PAB_REG_ADDR(0x4ba4, win)
85 #define PAB_PEX_AMAP_PEX_WIN_L(win) PAB_REG_ADDR(0x4ba8, win)
86 #define PAB_PEX_AMAP_PEX_WIN_H(win) PAB_REG_ADDR(0x4bac, win)
88 /* starting offset of INTX bits in status register */
89 #define PAB_INTX_START 5
91 /* supported number of MSI interrupts */
92 #define PCI_NUM_MSI 16
95 #define MSI_BASE_LO_OFFSET 0x04
96 #define MSI_BASE_HI_OFFSET 0x08
97 #define MSI_SIZE_OFFSET 0x0c
98 #define MSI_ENABLE_OFFSET 0x14
99 #define MSI_STATUS_OFFSET 0x18
100 #define MSI_DATA_OFFSET 0x20
101 #define MSI_ADDR_L_OFFSET 0x24
102 #define MSI_ADDR_H_OFFSET 0x28
104 /* outbound and inbound window definitions */
107 #define CFG_WINDOW_TYPE 0
108 #define IO_WINDOW_TYPE 1
109 #define MEM_WINDOW_TYPE 2
110 #define IB_WIN_SIZE (256 * 1024 * 1024 * 1024)
111 #define MAX_PIO_WINDOWS 8
113 /* Parameters for the waiting for link up routine */
114 #define LINK_WAIT_MAX_RETRIES 10
115 #define LINK_WAIT_MIN 90000
116 #define LINK_WAIT_MAX 100000
118 struct mobiveil_msi
{ /* MSI information */
119 struct mutex lock
; /* protect bitmap variable */
120 struct irq_domain
*msi_domain
;
121 struct irq_domain
*dev_domain
;
122 phys_addr_t msi_pages_phys
;
124 DECLARE_BITMAP(msi_irq_in_use
, PCI_NUM_MSI
);
127 struct mobiveil_pcie
{
128 struct platform_device
*pdev
;
129 struct list_head resources
;
130 void __iomem
*config_axi_slave_base
; /* endpoint config base */
131 void __iomem
*csr_axi_slave_base
; /* root port config base */
132 void __iomem
*apb_csr_base
; /* MSI register base */
133 void __iomem
*pcie_reg_base
; /* Physical PCIe Controller Base */
134 struct irq_domain
*intx_domain
;
135 raw_spinlock_t intx_mask_lock
;
139 int ob_wins_configured
; /* configured outbound windows */
140 int ib_wins_configured
; /* configured inbound windows */
141 struct resource
*ob_io_res
;
143 struct mobiveil_msi msi
;
146 static inline void csr_writel(struct mobiveil_pcie
*pcie
, const u32 value
,
149 writel_relaxed(value
, pcie
->csr_axi_slave_base
+ reg
);
152 static inline u32
csr_readl(struct mobiveil_pcie
*pcie
, const u32 reg
)
154 return readl_relaxed(pcie
->csr_axi_slave_base
+ reg
);
157 static bool mobiveil_pcie_link_up(struct mobiveil_pcie
*pcie
)
159 return (csr_readl(pcie
, LTSSM_STATUS
) &
160 LTSSM_STATUS_L0_MASK
) == LTSSM_STATUS_L0
;
163 static bool mobiveil_pcie_valid_device(struct pci_bus
*bus
, unsigned int devfn
)
165 struct mobiveil_pcie
*pcie
= bus
->sysdata
;
167 /* Only one device down on each root port */
168 if ((bus
->number
== pcie
->root_bus_nr
) && (devfn
> 0))
172 * Do not read more than one device on the bus directly
175 if ((bus
->primary
== pcie
->root_bus_nr
) && (devfn
> 0))
182 * mobiveil_pcie_map_bus - routine to get the configuration base of either
183 * root port or endpoint
185 static void __iomem
*mobiveil_pcie_map_bus(struct pci_bus
*bus
,
186 unsigned int devfn
, int where
)
188 struct mobiveil_pcie
*pcie
= bus
->sysdata
;
190 if (!mobiveil_pcie_valid_device(bus
, devfn
))
193 if (bus
->number
== pcie
->root_bus_nr
) {
194 /* RC config access */
195 return pcie
->csr_axi_slave_base
+ where
;
199 * EP config access (in Config/APIO space)
200 * Program PEX Address base (31..16 bits) with appropriate value
201 * (BDF) in PAB_AXI_AMAP_PEX_WIN_L0 Register.
202 * Relies on pci_lock serialization
204 csr_writel(pcie
, bus
->number
<< PAB_BUS_SHIFT
|
205 PCI_SLOT(devfn
) << PAB_DEVICE_SHIFT
|
206 PCI_FUNC(devfn
) << PAB_FUNCTION_SHIFT
,
207 PAB_AXI_AMAP_PEX_WIN_L(WIN_NUM_0
));
208 return pcie
->config_axi_slave_base
+ where
;
211 static struct pci_ops mobiveil_pcie_ops
= {
212 .map_bus
= mobiveil_pcie_map_bus
,
213 .read
= pci_generic_config_read
,
214 .write
= pci_generic_config_write
,
217 static void mobiveil_pcie_isr(struct irq_desc
*desc
)
219 struct irq_chip
*chip
= irq_desc_get_chip(desc
);
220 struct mobiveil_pcie
*pcie
= irq_desc_get_handler_data(desc
);
221 struct device
*dev
= &pcie
->pdev
->dev
;
222 struct mobiveil_msi
*msi
= &pcie
->msi
;
223 u32 msi_data
, msi_addr_lo
, msi_addr_hi
;
224 u32 intr_status
, msi_status
;
225 unsigned long shifted_status
;
226 u32 bit
, virq
, val
, mask
;
229 * The core provides a single interrupt for both INTx/MSI messages.
230 * So we'll read both INTx and MSI status
233 chained_irq_enter(chip
, desc
);
235 /* read INTx status */
236 val
= csr_readl(pcie
, PAB_INTP_AMBA_MISC_STAT
);
237 mask
= csr_readl(pcie
, PAB_INTP_AMBA_MISC_ENB
);
238 intr_status
= val
& mask
;
241 if (intr_status
& PAB_INTP_INTX_MASK
) {
242 shifted_status
= csr_readl(pcie
, PAB_INTP_AMBA_MISC_STAT
) >>
245 for_each_set_bit(bit
, &shifted_status
, PCI_NUM_INTX
) {
246 virq
= irq_find_mapping(pcie
->intx_domain
,
249 generic_handle_irq(virq
);
251 dev_err_ratelimited(dev
,
252 "unexpected IRQ, INT%d\n", bit
);
254 /* clear interrupt */
256 shifted_status
<< PAB_INTX_START
,
257 PAB_INTP_AMBA_MISC_STAT
);
259 } while ((shifted_status
>> PAB_INTX_START
) != 0);
262 /* read extra MSI status register */
263 msi_status
= readl_relaxed(pcie
->apb_csr_base
+ MSI_STATUS_OFFSET
);
265 /* handle MSI interrupts */
266 while (msi_status
& 1) {
267 msi_data
= readl_relaxed(pcie
->apb_csr_base
271 * MSI_STATUS_OFFSET register gets updated to zero
272 * once we pop not only the MSI data but also address
273 * from MSI hardware FIFO. So keeping these following
276 msi_addr_lo
= readl_relaxed(pcie
->apb_csr_base
+
278 msi_addr_hi
= readl_relaxed(pcie
->apb_csr_base
+
280 dev_dbg(dev
, "MSI registers, data: %08x, addr: %08x:%08x\n",
281 msi_data
, msi_addr_hi
, msi_addr_lo
);
283 virq
= irq_find_mapping(msi
->dev_domain
, msi_data
);
285 generic_handle_irq(virq
);
287 msi_status
= readl_relaxed(pcie
->apb_csr_base
+
291 /* Clear the interrupt status */
292 csr_writel(pcie
, intr_status
, PAB_INTP_AMBA_MISC_STAT
);
293 chained_irq_exit(chip
, desc
);
296 static int mobiveil_pcie_parse_dt(struct mobiveil_pcie
*pcie
)
298 struct device
*dev
= &pcie
->pdev
->dev
;
299 struct platform_device
*pdev
= pcie
->pdev
;
300 struct device_node
*node
= dev
->of_node
;
301 struct resource
*res
;
304 type
= of_get_property(node
, "device_type", NULL
);
305 if (!type
|| strcmp(type
, "pci")) {
306 dev_err(dev
, "invalid \"device_type\" %s\n", type
);
310 /* map config resource */
311 res
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
,
313 pcie
->config_axi_slave_base
= devm_pci_remap_cfg_resource(dev
, res
);
314 if (IS_ERR(pcie
->config_axi_slave_base
))
315 return PTR_ERR(pcie
->config_axi_slave_base
);
316 pcie
->ob_io_res
= res
;
318 /* map csr resource */
319 res
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
,
321 pcie
->csr_axi_slave_base
= devm_pci_remap_cfg_resource(dev
, res
);
322 if (IS_ERR(pcie
->csr_axi_slave_base
))
323 return PTR_ERR(pcie
->csr_axi_slave_base
);
324 pcie
->pcie_reg_base
= res
->start
;
326 /* map MSI config resource */
327 res
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
, "apb_csr");
328 pcie
->apb_csr_base
= devm_pci_remap_cfg_resource(dev
, res
);
329 if (IS_ERR(pcie
->apb_csr_base
))
330 return PTR_ERR(pcie
->apb_csr_base
);
332 /* read the number of windows requested */
333 if (of_property_read_u32(node
, "apio-wins", &pcie
->apio_wins
))
334 pcie
->apio_wins
= MAX_PIO_WINDOWS
;
336 if (of_property_read_u32(node
, "ppio-wins", &pcie
->ppio_wins
))
337 pcie
->ppio_wins
= MAX_PIO_WINDOWS
;
339 pcie
->irq
= platform_get_irq(pdev
, 0);
340 if (pcie
->irq
<= 0) {
341 dev_err(dev
, "failed to map IRQ: %d\n", pcie
->irq
);
345 irq_set_chained_handler_and_data(pcie
->irq
, mobiveil_pcie_isr
, pcie
);
351 * select_paged_register - routine to access paged register of root complex
353 * registers of RC are paged, for this scheme to work
354 * extracted higher 6 bits of the offset will be written to pg_sel
355 * field of PAB_CTRL register and rest of the lower 10 bits enabled with
356 * PAGE_SEL_EN are used as offset of the register.
358 static void select_paged_register(struct mobiveil_pcie
*pcie
, u32 offset
)
360 int pab_ctrl_dw
, pg_sel
;
362 /* clear pg_sel field */
363 pab_ctrl_dw
= csr_readl(pcie
, PAB_CTRL
);
364 pab_ctrl_dw
= (pab_ctrl_dw
& ~(PAGE_SEL_MASK
<< PAGE_SEL_SHIFT
));
366 /* set pg_sel field */
367 pg_sel
= (offset
>> PAGE_SEL_OFFSET_SHIFT
) & PAGE_SEL_MASK
;
368 pab_ctrl_dw
|= ((pg_sel
<< PAGE_SEL_SHIFT
));
369 csr_writel(pcie
, pab_ctrl_dw
, PAB_CTRL
);
372 static void write_paged_register(struct mobiveil_pcie
*pcie
,
375 u32 off
= (offset
& PAGE_LO_MASK
) | PAGE_SEL_EN
;
377 select_paged_register(pcie
, offset
);
378 csr_writel(pcie
, val
, off
);
381 static u32
read_paged_register(struct mobiveil_pcie
*pcie
, u32 offset
)
383 u32 off
= (offset
& PAGE_LO_MASK
) | PAGE_SEL_EN
;
385 select_paged_register(pcie
, offset
);
386 return csr_readl(pcie
, off
);
389 static void program_ib_windows(struct mobiveil_pcie
*pcie
, int win_num
,
390 int pci_addr
, u32 type
, u64 size
)
394 u64 size64
= ~(size
- 1);
396 if ((pcie
->ib_wins_configured
+ 1) > pcie
->ppio_wins
) {
397 dev_err(&pcie
->pdev
->dev
,
398 "ERROR: max inbound windows reached !\n");
402 pio_ctrl_val
= csr_readl(pcie
, PAB_PEX_PIO_CTRL
);
404 pio_ctrl_val
| (1 << PIO_ENABLE_SHIFT
), PAB_PEX_PIO_CTRL
);
405 amap_ctrl_dw
= read_paged_register(pcie
, PAB_PEX_AMAP_CTRL(win_num
));
406 amap_ctrl_dw
= (amap_ctrl_dw
| (type
<< AMAP_CTRL_TYPE_SHIFT
));
407 amap_ctrl_dw
= (amap_ctrl_dw
| (1 << AMAP_CTRL_EN_SHIFT
));
409 write_paged_register(pcie
, amap_ctrl_dw
| lower_32_bits(size64
),
410 PAB_PEX_AMAP_CTRL(win_num
));
412 write_paged_register(pcie
, upper_32_bits(size64
),
413 PAB_EXT_PEX_AMAP_SIZEN(win_num
));
415 write_paged_register(pcie
, pci_addr
, PAB_PEX_AMAP_AXI_WIN(win_num
));
416 write_paged_register(pcie
, pci_addr
, PAB_PEX_AMAP_PEX_WIN_L(win_num
));
417 write_paged_register(pcie
, 0, PAB_PEX_AMAP_PEX_WIN_H(win_num
));
421 * routine to program the outbound windows
423 static void program_ob_windows(struct mobiveil_pcie
*pcie
, int win_num
,
424 u64 cpu_addr
, u64 pci_addr
, u32 config_io_bit
, u64 size
)
428 u64 size64
= ~(size
- 1);
430 if ((pcie
->ob_wins_configured
+ 1) > pcie
->apio_wins
) {
431 dev_err(&pcie
->pdev
->dev
,
432 "ERROR: max outbound windows reached !\n");
437 * program Enable Bit to 1, Type Bit to (00) base 2, AXI Window Size Bit
438 * to 4 KB in PAB_AXI_AMAP_CTRL register
440 type
= config_io_bit
;
441 value
= csr_readl(pcie
, PAB_AXI_AMAP_CTRL(win_num
));
442 csr_writel(pcie
, 1 << WIN_ENABLE_SHIFT
| type
<< WIN_TYPE_SHIFT
|
443 lower_32_bits(size64
), PAB_AXI_AMAP_CTRL(win_num
));
445 write_paged_register(pcie
, upper_32_bits(size64
),
446 PAB_EXT_AXI_AMAP_SIZE(win_num
));
449 * program AXI window base with appropriate value in
450 * PAB_AXI_AMAP_AXI_WIN0 register
452 value
= csr_readl(pcie
, PAB_AXI_AMAP_AXI_WIN(win_num
));
453 csr_writel(pcie
, cpu_addr
& (~AXI_WINDOW_ALIGN_MASK
),
454 PAB_AXI_AMAP_AXI_WIN(win_num
));
456 value
= csr_readl(pcie
, PAB_AXI_AMAP_PEX_WIN_H(win_num
));
458 csr_writel(pcie
, lower_32_bits(pci_addr
),
459 PAB_AXI_AMAP_PEX_WIN_L(win_num
));
460 csr_writel(pcie
, upper_32_bits(pci_addr
),
461 PAB_AXI_AMAP_PEX_WIN_H(win_num
));
463 pcie
->ob_wins_configured
++;
466 static int mobiveil_bringup_link(struct mobiveil_pcie
*pcie
)
470 /* check if the link is up or not */
471 for (retries
= 0; retries
< LINK_WAIT_MAX_RETRIES
; retries
++) {
472 if (mobiveil_pcie_link_up(pcie
))
475 usleep_range(LINK_WAIT_MIN
, LINK_WAIT_MAX
);
477 dev_err(&pcie
->pdev
->dev
, "link never came up\n");
481 static void mobiveil_pcie_enable_msi(struct mobiveil_pcie
*pcie
)
483 phys_addr_t msg_addr
= pcie
->pcie_reg_base
;
484 struct mobiveil_msi
*msi
= &pcie
->msi
;
486 pcie
->msi
.num_of_vectors
= PCI_NUM_MSI
;
487 msi
->msi_pages_phys
= (phys_addr_t
)msg_addr
;
489 writel_relaxed(lower_32_bits(msg_addr
),
490 pcie
->apb_csr_base
+ MSI_BASE_LO_OFFSET
);
491 writel_relaxed(upper_32_bits(msg_addr
),
492 pcie
->apb_csr_base
+ MSI_BASE_HI_OFFSET
);
493 writel_relaxed(4096, pcie
->apb_csr_base
+ MSI_SIZE_OFFSET
);
494 writel_relaxed(1, pcie
->apb_csr_base
+ MSI_ENABLE_OFFSET
);
497 static int mobiveil_host_init(struct mobiveil_pcie
*pcie
)
499 u32 value
, pab_ctrl
, type
= 0;
501 struct resource_entry
*win
, *tmp
;
503 err
= mobiveil_bringup_link(pcie
);
505 dev_info(&pcie
->pdev
->dev
, "link bring-up failed\n");
510 * program Bus Master Enable Bit in Command Register in PAB Config
513 value
= csr_readl(pcie
, PCI_COMMAND
);
514 csr_writel(pcie
, value
| PCI_COMMAND_IO
| PCI_COMMAND_MEMORY
|
515 PCI_COMMAND_MASTER
, PCI_COMMAND
);
518 * program PIO Enable Bit to 1 (and PEX PIO Enable to 1) in PAB_CTRL
521 pab_ctrl
= csr_readl(pcie
, PAB_CTRL
);
522 csr_writel(pcie
, pab_ctrl
| (1 << AMBA_PIO_ENABLE_SHIFT
) |
523 (1 << PEX_PIO_ENABLE_SHIFT
), PAB_CTRL
);
525 csr_writel(pcie
, (PAB_INTP_INTX_MASK
| PAB_INTP_MSI_MASK
),
526 PAB_INTP_AMBA_MISC_ENB
);
529 * program PIO Enable Bit to 1 and Config Window Enable Bit to 1 in
530 * PAB_AXI_PIO_CTRL Register
532 value
= csr_readl(pcie
, PAB_AXI_PIO_CTRL
);
533 csr_writel(pcie
, value
| APIO_EN_MASK
, PAB_AXI_PIO_CTRL
);
536 * we'll program one outbound window for config reads and
537 * another default inbound window for all the upstream traffic
538 * rest of the outbound windows will be configured according to
539 * the "ranges" field defined in device tree
542 /* config outbound translation window */
543 program_ob_windows(pcie
, pcie
->ob_wins_configured
,
544 pcie
->ob_io_res
->start
, 0, CFG_WINDOW_TYPE
,
545 resource_size(pcie
->ob_io_res
));
547 /* memory inbound translation window */
548 program_ib_windows(pcie
, WIN_NUM_1
, 0, MEM_WINDOW_TYPE
, IB_WIN_SIZE
);
550 /* Get the I/O and memory ranges from DT */
551 resource_list_for_each_entry_safe(win
, tmp
, &pcie
->resources
) {
553 if (resource_type(win
->res
) == IORESOURCE_MEM
)
554 type
= MEM_WINDOW_TYPE
;
555 if (resource_type(win
->res
) == IORESOURCE_IO
)
556 type
= IO_WINDOW_TYPE
;
558 /* configure outbound translation window */
559 program_ob_windows(pcie
, pcie
->ob_wins_configured
,
560 win
->res
->start
, 0, type
,
561 resource_size(win
->res
));
565 /* setup MSI hardware registers */
566 mobiveil_pcie_enable_msi(pcie
);
571 static void mobiveil_mask_intx_irq(struct irq_data
*data
)
573 struct irq_desc
*desc
= irq_to_desc(data
->irq
);
574 struct mobiveil_pcie
*pcie
;
576 u32 mask
, shifted_val
;
578 pcie
= irq_desc_get_chip_data(desc
);
579 mask
= 1 << ((data
->hwirq
+ PAB_INTX_START
) - 1);
580 raw_spin_lock_irqsave(&pcie
->intx_mask_lock
, flags
);
581 shifted_val
= csr_readl(pcie
, PAB_INTP_AMBA_MISC_ENB
);
582 csr_writel(pcie
, (shifted_val
& (~mask
)), PAB_INTP_AMBA_MISC_ENB
);
583 raw_spin_unlock_irqrestore(&pcie
->intx_mask_lock
, flags
);
586 static void mobiveil_unmask_intx_irq(struct irq_data
*data
)
588 struct irq_desc
*desc
= irq_to_desc(data
->irq
);
589 struct mobiveil_pcie
*pcie
;
591 u32 shifted_val
, mask
;
593 pcie
= irq_desc_get_chip_data(desc
);
594 mask
= 1 << ((data
->hwirq
+ PAB_INTX_START
) - 1);
595 raw_spin_lock_irqsave(&pcie
->intx_mask_lock
, flags
);
596 shifted_val
= csr_readl(pcie
, PAB_INTP_AMBA_MISC_ENB
);
597 csr_writel(pcie
, (shifted_val
| mask
), PAB_INTP_AMBA_MISC_ENB
);
598 raw_spin_unlock_irqrestore(&pcie
->intx_mask_lock
, flags
);
601 static struct irq_chip intx_irq_chip
= {
602 .name
= "mobiveil_pcie:intx",
603 .irq_enable
= mobiveil_unmask_intx_irq
,
604 .irq_disable
= mobiveil_mask_intx_irq
,
605 .irq_mask
= mobiveil_mask_intx_irq
,
606 .irq_unmask
= mobiveil_unmask_intx_irq
,
609 /* routine to setup the INTx related data */
610 static int mobiveil_pcie_intx_map(struct irq_domain
*domain
, unsigned int irq
,
611 irq_hw_number_t hwirq
)
613 irq_set_chip_and_handler(irq
, &intx_irq_chip
, handle_level_irq
);
614 irq_set_chip_data(irq
, domain
->host_data
);
618 /* INTx domain operations structure */
619 static const struct irq_domain_ops intx_domain_ops
= {
620 .map
= mobiveil_pcie_intx_map
,
623 static struct irq_chip mobiveil_msi_irq_chip
= {
624 .name
= "Mobiveil PCIe MSI",
625 .irq_mask
= pci_msi_mask_irq
,
626 .irq_unmask
= pci_msi_unmask_irq
,
629 static struct msi_domain_info mobiveil_msi_domain_info
= {
630 .flags
= (MSI_FLAG_USE_DEF_DOM_OPS
| MSI_FLAG_USE_DEF_CHIP_OPS
|
631 MSI_FLAG_MULTI_PCI_MSI
| MSI_FLAG_PCI_MSIX
),
632 .chip
= &mobiveil_msi_irq_chip
,
635 static void mobiveil_compose_msi_msg(struct irq_data
*data
, struct msi_msg
*msg
)
637 struct mobiveil_pcie
*pcie
= irq_data_get_irq_chip_data(data
);
638 phys_addr_t addr
= pcie
->pcie_reg_base
+ (data
->hwirq
* sizeof(int));
640 msg
->address_lo
= lower_32_bits(addr
);
641 msg
->address_hi
= upper_32_bits(addr
);
642 msg
->data
= data
->hwirq
;
644 dev_dbg(&pcie
->pdev
->dev
, "msi#%d address_hi %#x address_lo %#x\n",
645 (int)data
->hwirq
, msg
->address_hi
, msg
->address_lo
);
648 static int mobiveil_msi_set_affinity(struct irq_data
*irq_data
,
649 const struct cpumask
*mask
, bool force
)
654 static struct irq_chip mobiveil_msi_bottom_irq_chip
= {
655 .name
= "Mobiveil MSI",
656 .irq_compose_msi_msg
= mobiveil_compose_msi_msg
,
657 .irq_set_affinity
= mobiveil_msi_set_affinity
,
660 static int mobiveil_irq_msi_domain_alloc(struct irq_domain
*domain
,
661 unsigned int virq
, unsigned int nr_irqs
, void *args
)
663 struct mobiveil_pcie
*pcie
= domain
->host_data
;
664 struct mobiveil_msi
*msi
= &pcie
->msi
;
667 WARN_ON(nr_irqs
!= 1);
668 mutex_lock(&msi
->lock
);
670 bit
= find_first_zero_bit(msi
->msi_irq_in_use
, msi
->num_of_vectors
);
671 if (bit
>= msi
->num_of_vectors
) {
672 mutex_unlock(&msi
->lock
);
676 set_bit(bit
, msi
->msi_irq_in_use
);
678 mutex_unlock(&msi
->lock
);
680 irq_domain_set_info(domain
, virq
, bit
, &mobiveil_msi_bottom_irq_chip
,
681 domain
->host_data
, handle_level_irq
,
686 static void mobiveil_irq_msi_domain_free(struct irq_domain
*domain
,
687 unsigned int virq
, unsigned int nr_irqs
)
689 struct irq_data
*d
= irq_domain_get_irq_data(domain
, virq
);
690 struct mobiveil_pcie
*pcie
= irq_data_get_irq_chip_data(d
);
691 struct mobiveil_msi
*msi
= &pcie
->msi
;
693 mutex_lock(&msi
->lock
);
695 if (!test_bit(d
->hwirq
, msi
->msi_irq_in_use
)) {
696 dev_err(&pcie
->pdev
->dev
, "trying to free unused MSI#%lu\n",
699 __clear_bit(d
->hwirq
, msi
->msi_irq_in_use
);
702 mutex_unlock(&msi
->lock
);
704 static const struct irq_domain_ops msi_domain_ops
= {
705 .alloc
= mobiveil_irq_msi_domain_alloc
,
706 .free
= mobiveil_irq_msi_domain_free
,
709 static int mobiveil_allocate_msi_domains(struct mobiveil_pcie
*pcie
)
711 struct device
*dev
= &pcie
->pdev
->dev
;
712 struct fwnode_handle
*fwnode
= of_node_to_fwnode(dev
->of_node
);
713 struct mobiveil_msi
*msi
= &pcie
->msi
;
715 mutex_init(&pcie
->msi
.lock
);
716 msi
->dev_domain
= irq_domain_add_linear(NULL
, msi
->num_of_vectors
,
717 &msi_domain_ops
, pcie
);
718 if (!msi
->dev_domain
) {
719 dev_err(dev
, "failed to create IRQ domain\n");
723 msi
->msi_domain
= pci_msi_create_irq_domain(fwnode
,
724 &mobiveil_msi_domain_info
, msi
->dev_domain
);
725 if (!msi
->msi_domain
) {
726 dev_err(dev
, "failed to create MSI domain\n");
727 irq_domain_remove(msi
->dev_domain
);
733 static int mobiveil_pcie_init_irq_domain(struct mobiveil_pcie
*pcie
)
735 struct device
*dev
= &pcie
->pdev
->dev
;
736 struct device_node
*node
= dev
->of_node
;
740 pcie
->intx_domain
= irq_domain_add_linear(node
,
741 PCI_NUM_INTX
, &intx_domain_ops
, pcie
);
743 if (!pcie
->intx_domain
) {
744 dev_err(dev
, "Failed to get a INTx IRQ domain\n");
748 raw_spin_lock_init(&pcie
->intx_mask_lock
);
751 ret
= mobiveil_allocate_msi_domains(pcie
);
758 static int mobiveil_pcie_probe(struct platform_device
*pdev
)
760 struct mobiveil_pcie
*pcie
;
762 struct pci_bus
*child
;
763 struct pci_host_bridge
*bridge
;
764 struct device
*dev
= &pdev
->dev
;
765 resource_size_t iobase
;
768 /* allocate the PCIe port */
769 bridge
= devm_pci_alloc_host_bridge(dev
, sizeof(*pcie
));
773 pcie
= pci_host_bridge_priv(bridge
);
779 ret
= mobiveil_pcie_parse_dt(pcie
);
781 dev_err(dev
, "Parsing DT failed, ret: %x\n", ret
);
785 INIT_LIST_HEAD(&pcie
->resources
);
787 /* parse the host bridge base addresses from the device tree file */
788 ret
= devm_of_pci_get_host_bridge_resources(dev
, 0, 0xff,
789 &pcie
->resources
, &iobase
);
791 dev_err(dev
, "Getting bridge resources failed\n");
796 * configure all inbound and outbound windows and prepare the RC for
799 ret
= mobiveil_host_init(pcie
);
801 dev_err(dev
, "Failed to initialize host\n");
805 /* fixup for PCIe class register */
806 csr_writel(pcie
, 0x060402ab, PAB_INTP_AXI_PIO_CLASS
);
808 /* initialize the IRQ domains */
809 ret
= mobiveil_pcie_init_irq_domain(pcie
);
811 dev_err(dev
, "Failed creating IRQ Domain\n");
815 ret
= devm_request_pci_bus_resources(dev
, &pcie
->resources
);
819 /* Initialize bridge */
820 list_splice_init(&pcie
->resources
, &bridge
->windows
);
821 bridge
->dev
.parent
= dev
;
822 bridge
->sysdata
= pcie
;
823 bridge
->busnr
= pcie
->root_bus_nr
;
824 bridge
->ops
= &mobiveil_pcie_ops
;
825 bridge
->map_irq
= of_irq_parse_and_map_pci
;
826 bridge
->swizzle_irq
= pci_common_swizzle
;
828 /* setup the kernel resources for the newly added PCIe root bus */
829 ret
= pci_scan_root_bus_bridge(bridge
);
835 pci_assign_unassigned_bus_resources(bus
);
836 list_for_each_entry(child
, &bus
->children
, node
)
837 pcie_bus_configure_settings(child
);
838 pci_bus_add_devices(bus
);
842 pci_free_resource_list(&pcie
->resources
);
846 static const struct of_device_id mobiveil_pcie_of_match
[] = {
847 {.compatible
= "mbvl,gpex40-pcie",},
851 MODULE_DEVICE_TABLE(of
, mobiveil_pcie_of_match
);
853 static struct platform_driver mobiveil_pcie_driver
= {
854 .probe
= mobiveil_pcie_probe
,
856 .name
= "mobiveil-pcie",
857 .of_match_table
= mobiveil_pcie_of_match
,
858 .suppress_bind_attrs
= true,
862 builtin_platform_driver(mobiveil_pcie_driver
);
864 MODULE_LICENSE("GPL v2");
865 MODULE_DESCRIPTION("Mobiveil PCIe host controller driver");
866 MODULE_AUTHOR("Subrahmanya Lingappa <l.subrahmanya@mobiveil.co.in>");