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. For this to work, we must place
69 * the first device on the same bus as the CNS PCI bridge.
71 if (busno
== 0) { /* internal PCIe bus, host bridge device */
72 if (devfn
== 0) /* device# and function# are ignored by hw */
73 base
= cnspci
->host_regs
;
75 return NULL
; /* no such device */
77 } else if (busno
== 1) { /* directly connected PCIe device */
78 if (slot
== 0) /* device# is ignored by hw */
79 base
= cnspci
->cfg0_regs
;
81 return NULL
; /* no such device */
82 } else /* remote PCI bus */
83 base
= cnspci
->cfg1_regs
+ ((busno
& 0xf) << 20);
85 return base
+ (where
& 0xffc) + (devfn
<< 12);
88 static int cns3xxx_pci_read_config(struct pci_bus
*bus
, unsigned int devfn
,
89 int where
, int size
, u32
*val
)
92 u32 mask
= (0x1ull
<< (size
* 8)) - 1;
93 int shift
= (where
% 4) * 8;
95 ret
= pci_generic_config_read32(bus
, devfn
, where
, size
, val
);
97 if (ret
== PCIBIOS_SUCCESSFUL
&& !bus
->number
&& !devfn
&&
98 (where
& 0xffc) == PCI_CLASS_REVISION
)
100 * RC's class is 0xb, but Linux PCI driver needs 0x604
101 * for a PCIe bridge. So we must fixup the class code
104 *val
= ((((*val
<< shift
) & 0xff) | (0x604 << 16)) >> shift
) & mask
;
109 static int cns3xxx_pci_setup(int nr
, struct pci_sys_data
*sys
)
111 struct cns3xxx_pcie
*cnspci
= sysdata_to_cnspci(sys
);
112 struct resource
*res_io
= &cnspci
->res_io
;
113 struct resource
*res_mem
= &cnspci
->res_mem
;
115 BUG_ON(request_resource(&iomem_resource
, res_io
) ||
116 request_resource(&iomem_resource
, res_mem
));
118 pci_add_resource_offset(&sys
->resources
, res_io
, sys
->io_offset
);
119 pci_add_resource_offset(&sys
->resources
, res_mem
, sys
->mem_offset
);
124 static struct pci_ops cns3xxx_pcie_ops
= {
125 .map_bus
= cns3xxx_pci_map_bus
,
126 .read
= cns3xxx_pci_read_config
,
127 .write
= pci_generic_config_write
,
130 static int cns3xxx_pcie_map_irq(const struct pci_dev
*dev
, u8 slot
, u8 pin
)
132 struct cns3xxx_pcie
*cnspci
= pdev_to_cnspci(dev
);
133 int irq
= cnspci
->irqs
[!!dev
->bus
->number
];
135 pr_info("PCIe map irq: %04d:%02x:%02x.%02x slot %d, pin %d, irq: %d\n",
136 pci_domain_nr(dev
->bus
), dev
->bus
->number
, PCI_SLOT(dev
->devfn
),
137 PCI_FUNC(dev
->devfn
), slot
, pin
, irq
);
142 static struct cns3xxx_pcie cns3xxx_pcie
[] = {
144 .host_regs
= (void __iomem
*)CNS3XXX_PCIE0_HOST_BASE_VIRT
,
145 .cfg0_regs
= (void __iomem
*)CNS3XXX_PCIE0_CFG0_BASE_VIRT
,
146 .cfg1_regs
= (void __iomem
*)CNS3XXX_PCIE0_CFG1_BASE_VIRT
,
148 .name
= "PCIe0 I/O space",
149 .start
= CNS3XXX_PCIE0_IO_BASE
,
150 .end
= CNS3XXX_PCIE0_CFG0_BASE
- 1, /* 16 MiB */
151 .flags
= IORESOURCE_IO
,
154 .name
= "PCIe0 non-prefetchable",
155 .start
= CNS3XXX_PCIE0_MEM_BASE
,
156 .end
= CNS3XXX_PCIE0_HOST_BASE
- 1, /* 176 MiB */
157 .flags
= IORESOURCE_MEM
,
159 .irqs
= { IRQ_CNS3XXX_PCIE0_RC
, IRQ_CNS3XXX_PCIE0_DEVICE
, },
163 .host_regs
= (void __iomem
*)CNS3XXX_PCIE1_HOST_BASE_VIRT
,
164 .cfg0_regs
= (void __iomem
*)CNS3XXX_PCIE1_CFG0_BASE_VIRT
,
165 .cfg1_regs
= (void __iomem
*)CNS3XXX_PCIE1_CFG1_BASE_VIRT
,
167 .name
= "PCIe1 I/O space",
168 .start
= CNS3XXX_PCIE1_IO_BASE
,
169 .end
= CNS3XXX_PCIE1_CFG0_BASE
- 1, /* 16 MiB */
170 .flags
= IORESOURCE_IO
,
173 .name
= "PCIe1 non-prefetchable",
174 .start
= CNS3XXX_PCIE1_MEM_BASE
,
175 .end
= CNS3XXX_PCIE1_HOST_BASE
- 1, /* 176 MiB */
176 .flags
= IORESOURCE_MEM
,
178 .irqs
= { IRQ_CNS3XXX_PCIE1_RC
, IRQ_CNS3XXX_PCIE1_DEVICE
, },
183 static void __init
cns3xxx_pcie_check_link(struct cns3xxx_pcie
*cnspci
)
185 int port
= cnspci
->port
;
189 reg
= __raw_readl(MISC_PCIE_CTRL(port
));
191 * Enable Application Request to 1, it will exit L1 automatically,
192 * but when chip back, it will use another clock, still can use 0x1.
195 __raw_writel(reg
, MISC_PCIE_CTRL(port
));
197 pr_info("PCIe: Port[%d] Enable PCIe LTSSM\n", port
);
198 pr_info("PCIe: Port[%d] Check data link layer...", port
);
202 reg
= __raw_readl(MISC_PCIE_PM_DEBUG(port
));
204 pr_info("Link up.\n");
207 } else if (time_after(jiffies
, time
+ 50)) {
208 pr_info("Device not found.\n");
214 static void __init
cns3xxx_pcie_hw_init(struct cns3xxx_pcie
*cnspci
)
216 int port
= cnspci
->port
;
217 struct pci_sys_data sd
= {
218 .private_data
= cnspci
,
220 struct pci_bus bus
= {
222 .ops
= &cns3xxx_pcie_ops
,
225 u16 mem_base
= cnspci
->res_mem
.start
>> 16;
226 u16 mem_limit
= cnspci
->res_mem
.end
>> 16;
227 u16 io_base
= cnspci
->res_io
.start
>> 16;
228 u16 io_limit
= cnspci
->res_io
.end
>> 16;
234 pci_bus_write_config_byte(&bus
, devfn
, PCI_PRIMARY_BUS
, 0);
235 pci_bus_write_config_byte(&bus
, devfn
, PCI_SECONDARY_BUS
, 1);
236 pci_bus_write_config_byte(&bus
, devfn
, PCI_SUBORDINATE_BUS
, 1);
238 pci_bus_read_config_byte(&bus
, devfn
, PCI_PRIMARY_BUS
, &tmp8
);
239 pci_bus_read_config_byte(&bus
, devfn
, PCI_SECONDARY_BUS
, &tmp8
);
240 pci_bus_read_config_byte(&bus
, devfn
, PCI_SUBORDINATE_BUS
, &tmp8
);
242 pci_bus_write_config_word(&bus
, devfn
, PCI_MEMORY_BASE
, mem_base
);
243 pci_bus_write_config_word(&bus
, devfn
, PCI_MEMORY_LIMIT
, mem_limit
);
244 pci_bus_write_config_word(&bus
, devfn
, PCI_IO_BASE_UPPER16
, io_base
);
245 pci_bus_write_config_word(&bus
, devfn
, PCI_IO_LIMIT_UPPER16
, io_limit
);
250 /* Set Device Max_Read_Request_Size to 128 byte */
251 bus
.number
= 1; /* directly connected PCIe device */
252 devfn
= PCI_DEVFN(0, 0);
253 pos
= pci_bus_find_capability(&bus
, devfn
, PCI_CAP_ID_EXP
);
254 pci_bus_read_config_word(&bus
, devfn
, pos
+ PCI_EXP_DEVCTL
, &dc
);
255 if (dc
& PCI_EXP_DEVCTL_READRQ
) {
256 dc
&= ~PCI_EXP_DEVCTL_READRQ
;
257 pci_bus_write_config_word(&bus
, devfn
, pos
+ PCI_EXP_DEVCTL
, dc
);
258 pci_bus_read_config_word(&bus
, devfn
, pos
+ PCI_EXP_DEVCTL
, &dc
);
259 if (dc
& PCI_EXP_DEVCTL_READRQ
)
260 pr_warn("PCIe: Unable to set device Max_Read_Request_Size\n");
262 pr_info("PCIe: Max_Read_Request_Size set to 128 bytes\n");
264 /* Disable PCIe0 Interrupt Mask INTA to INTD */
265 __raw_writel(~0x3FFF, MISC_PCIE_INT_MASK(port
));
268 static int cns3xxx_pcie_abort_handler(unsigned long addr
, unsigned int fsr
,
269 struct pt_regs
*regs
)
276 void __init
cns3xxx_pcie_init_late(void)
280 struct hw_pci hw_pci
= {
282 .ops
= &cns3xxx_pcie_ops
,
283 .setup
= cns3xxx_pci_setup
,
284 .map_irq
= cns3xxx_pcie_map_irq
,
285 .private_data
= &private_data
,
291 hook_fault_code(16 + 6, cns3xxx_pcie_abort_handler
, SIGBUS
, 0,
292 "imprecise external abort");
294 for (i
= 0; i
< ARRAY_SIZE(cns3xxx_pcie
); i
++) {
295 cns3xxx_pwr_clk_en(0x1 << PM_CLK_GATE_REG_OFFSET_PCIE(i
));
296 cns3xxx_pwr_soft_rst(0x1 << PM_SOFT_RST_REG_OFFST_PCIE(i
));
297 cns3xxx_pcie_check_link(&cns3xxx_pcie
[i
]);
298 cns3xxx_pcie_hw_init(&cns3xxx_pcie
[i
]);
299 private_data
= &cns3xxx_pcie
[i
];
300 pci_common_init(&hw_pci
);
303 pci_assign_unassigned_resources();