2 * PCI-E support for CNS3xxx
4 * Copyright 2008 Cavium Networks
5 * Richard Liu <richard.liu@caviumnetworks.com>
6 * Copyright 2010 MontaVista Software, LLC.
7 * Anton Vorontsov <avorontsov@mvista.com>
9 * This file is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License, Version 2, as
11 * published by the Free Software Foundation.
14 #include <linux/init.h>
15 #include <linux/kernel.h>
16 #include <linux/bug.h>
17 #include <linux/pci.h>
19 #include <linux/ioport.h>
20 #include <linux/interrupt.h>
21 #include <linux/ptrace.h>
22 #include <asm/mach/map.h>
27 void __iomem
*host_regs
; /* PCI config registers for host bridge */
28 void __iomem
*cfg0_regs
; /* PCI Type 0 config registers */
29 void __iomem
*cfg1_regs
; /* PCI Type 1 config registers */
31 struct resource res_io
;
32 struct resource res_mem
;
37 static struct cns3xxx_pcie
*sysdata_to_cnspci(void *sysdata
)
39 struct pci_sys_data
*root
= sysdata
;
41 return root
->private_data
;
44 static struct cns3xxx_pcie
*pdev_to_cnspci(const struct pci_dev
*dev
)
46 return sysdata_to_cnspci(dev
->sysdata
);
49 static struct cns3xxx_pcie
*pbus_to_cnspci(struct pci_bus
*bus
)
51 return sysdata_to_cnspci(bus
->sysdata
);
54 static void __iomem
*cns3xxx_pci_map_bus(struct pci_bus
*bus
,
55 unsigned int devfn
, int where
)
57 struct cns3xxx_pcie
*cnspci
= pbus_to_cnspci(bus
);
58 int busno
= bus
->number
;
59 int slot
= PCI_SLOT(devfn
);
62 /* If there is no link, just show the CNS PCI bridge. */
63 if (!cnspci
->linked
&& busno
> 0)
67 * The CNS PCI bridge doesn't fit into the PCI hierarchy, though
68 * we still want to access it.
69 * We place the host bridge on bus 0, and the directly connected
70 * device on bus 1, slot 0.
72 if (busno
== 0) { /* internal PCIe bus, host bridge device */
73 if (devfn
== 0) /* device# and function# are ignored by hw */
74 base
= cnspci
->host_regs
;
76 return NULL
; /* no such device */
78 } else if (busno
== 1) { /* directly connected PCIe device */
79 if (slot
== 0) /* device# is ignored by hw */
80 base
= cnspci
->cfg0_regs
;
82 return NULL
; /* no such device */
83 } else /* remote PCI bus */
84 base
= cnspci
->cfg1_regs
+ ((busno
& 0xf) << 20);
86 return base
+ (where
& 0xffc) + (devfn
<< 12);
89 static int cns3xxx_pci_read_config(struct pci_bus
*bus
, unsigned int devfn
,
90 int where
, int size
, u32
*val
)
93 u32 mask
= (0x1ull
<< (size
* 8)) - 1;
94 int shift
= (where
% 4) * 8;
96 ret
= pci_generic_config_read32(bus
, devfn
, where
, size
, val
);
98 if (ret
== PCIBIOS_SUCCESSFUL
&& !bus
->number
&& !devfn
&&
99 (where
& 0xffc) == PCI_CLASS_REVISION
)
101 * RC's class is 0xb, but Linux PCI driver needs 0x604
102 * for a PCIe bridge. So we must fixup the class code
105 *val
= ((((*val
<< shift
) & 0xff) | (0x604 << 16)) >> shift
) & mask
;
110 static int cns3xxx_pci_setup(int nr
, struct pci_sys_data
*sys
)
112 struct cns3xxx_pcie
*cnspci
= sysdata_to_cnspci(sys
);
113 struct resource
*res_io
= &cnspci
->res_io
;
114 struct resource
*res_mem
= &cnspci
->res_mem
;
116 BUG_ON(request_resource(&iomem_resource
, res_io
) ||
117 request_resource(&iomem_resource
, res_mem
));
119 pci_add_resource_offset(&sys
->resources
, res_io
, sys
->io_offset
);
120 pci_add_resource_offset(&sys
->resources
, res_mem
, sys
->mem_offset
);
125 static struct pci_ops cns3xxx_pcie_ops
= {
126 .map_bus
= cns3xxx_pci_map_bus
,
127 .read
= cns3xxx_pci_read_config
,
128 .write
= pci_generic_config_write
,
131 static int cns3xxx_pcie_map_irq(const struct pci_dev
*dev
, u8 slot
, u8 pin
)
133 struct cns3xxx_pcie
*cnspci
= pdev_to_cnspci(dev
);
134 int irq
= cnspci
->irqs
[!!dev
->bus
->number
];
136 pr_info("PCIe map irq: %04d:%02x:%02x.%02x slot %d, pin %d, irq: %d\n",
137 pci_domain_nr(dev
->bus
), dev
->bus
->number
, PCI_SLOT(dev
->devfn
),
138 PCI_FUNC(dev
->devfn
), slot
, pin
, irq
);
143 static struct cns3xxx_pcie cns3xxx_pcie
[] = {
145 .host_regs
= (void __iomem
*)CNS3XXX_PCIE0_HOST_BASE_VIRT
,
146 .cfg0_regs
= (void __iomem
*)CNS3XXX_PCIE0_CFG0_BASE_VIRT
,
147 .cfg1_regs
= (void __iomem
*)CNS3XXX_PCIE0_CFG1_BASE_VIRT
,
149 .name
= "PCIe0 I/O space",
150 .start
= CNS3XXX_PCIE0_IO_BASE
,
151 .end
= CNS3XXX_PCIE0_CFG0_BASE
- 1, /* 16 MiB */
152 .flags
= IORESOURCE_IO
,
155 .name
= "PCIe0 non-prefetchable",
156 .start
= CNS3XXX_PCIE0_MEM_BASE
,
157 .end
= CNS3XXX_PCIE0_HOST_BASE
- 1, /* 176 MiB */
158 .flags
= IORESOURCE_MEM
,
160 .irqs
= { IRQ_CNS3XXX_PCIE0_RC
, IRQ_CNS3XXX_PCIE0_DEVICE
, },
164 .host_regs
= (void __iomem
*)CNS3XXX_PCIE1_HOST_BASE_VIRT
,
165 .cfg0_regs
= (void __iomem
*)CNS3XXX_PCIE1_CFG0_BASE_VIRT
,
166 .cfg1_regs
= (void __iomem
*)CNS3XXX_PCIE1_CFG1_BASE_VIRT
,
168 .name
= "PCIe1 I/O space",
169 .start
= CNS3XXX_PCIE1_IO_BASE
,
170 .end
= CNS3XXX_PCIE1_CFG0_BASE
- 1, /* 16 MiB */
171 .flags
= IORESOURCE_IO
,
174 .name
= "PCIe1 non-prefetchable",
175 .start
= CNS3XXX_PCIE1_MEM_BASE
,
176 .end
= CNS3XXX_PCIE1_HOST_BASE
- 1, /* 176 MiB */
177 .flags
= IORESOURCE_MEM
,
179 .irqs
= { IRQ_CNS3XXX_PCIE1_RC
, IRQ_CNS3XXX_PCIE1_DEVICE
, },
184 static void __init
cns3xxx_pcie_check_link(struct cns3xxx_pcie
*cnspci
)
186 int port
= cnspci
->port
;
190 reg
= __raw_readl(MISC_PCIE_CTRL(port
));
192 * Enable Application Request to 1, it will exit L1 automatically,
193 * but when chip back, it will use another clock, still can use 0x1.
196 __raw_writel(reg
, MISC_PCIE_CTRL(port
));
198 pr_info("PCIe: Port[%d] Enable PCIe LTSSM\n", port
);
199 pr_info("PCIe: Port[%d] Check data link layer...", port
);
203 reg
= __raw_readl(MISC_PCIE_PM_DEBUG(port
));
205 pr_info("Link up.\n");
208 } else if (time_after(jiffies
, time
+ 50)) {
209 pr_info("Device not found.\n");
215 static void cns3xxx_write_config(struct cns3xxx_pcie
*cnspci
,
216 int where
, int size
, u32 val
)
218 void __iomem
*base
= cnspci
->host_regs
+ (where
& 0xffc);
220 u32 mask
= (0x1ull
<< (size
* 8)) - 1;
221 int shift
= (where
% 4) * 8;
223 v
= readl_relaxed(base
);
225 v
&= ~(mask
<< shift
);
226 v
|= (val
& mask
) << shift
;
228 writel_relaxed(v
, base
);
232 static void __init
cns3xxx_pcie_hw_init(struct cns3xxx_pcie
*cnspci
)
234 u16 mem_base
= cnspci
->res_mem
.start
>> 16;
235 u16 mem_limit
= cnspci
->res_mem
.end
>> 16;
236 u16 io_base
= cnspci
->res_io
.start
>> 16;
237 u16 io_limit
= cnspci
->res_io
.end
>> 16;
239 cns3xxx_write_config(cnspci
, PCI_PRIMARY_BUS
, 1, 0);
240 cns3xxx_write_config(cnspci
, PCI_SECONDARY_BUS
, 1, 1);
241 cns3xxx_write_config(cnspci
, PCI_SUBORDINATE_BUS
, 1, 1);
242 cns3xxx_write_config(cnspci
, PCI_MEMORY_BASE
, 2, mem_base
);
243 cns3xxx_write_config(cnspci
, PCI_MEMORY_LIMIT
, 2, mem_limit
);
244 cns3xxx_write_config(cnspci
, PCI_IO_BASE_UPPER16
, 2, io_base
);
245 cns3xxx_write_config(cnspci
, PCI_IO_LIMIT_UPPER16
, 2, io_limit
);
250 /* Set Device Max_Read_Request_Size to 128 byte */
251 pcie_bus_config
= PCIE_BUS_PEER2PEER
;
253 /* Disable PCIe0 Interrupt Mask INTA to INTD */
254 __raw_writel(~0x3FFF, MISC_PCIE_INT_MASK(cnspci
->port
));
257 static int cns3xxx_pcie_abort_handler(unsigned long addr
, unsigned int fsr
,
258 struct pt_regs
*regs
)
265 void __init
cns3xxx_pcie_init_late(void)
269 struct hw_pci hw_pci
= {
271 .ops
= &cns3xxx_pcie_ops
,
272 .setup
= cns3xxx_pci_setup
,
273 .map_irq
= cns3xxx_pcie_map_irq
,
274 .private_data
= &private_data
,
280 hook_fault_code(16 + 6, cns3xxx_pcie_abort_handler
, SIGBUS
, 0,
281 "imprecise external abort");
283 for (i
= 0; i
< ARRAY_SIZE(cns3xxx_pcie
); i
++) {
284 cns3xxx_pwr_clk_en(0x1 << PM_CLK_GATE_REG_OFFSET_PCIE(i
));
285 cns3xxx_pwr_soft_rst(0x1 << PM_SOFT_RST_REG_OFFST_PCIE(i
));
286 cns3xxx_pcie_check_link(&cns3xxx_pcie
[i
]);
287 cns3xxx_pcie_hw_init(&cns3xxx_pcie
[i
]);
288 private_data
= &cns3xxx_pcie
[i
];
289 pci_common_init(&hw_pci
);
292 pci_assign_unassigned_resources();