MIPS: BCM63XX: add core reset helper
[deliverable/linux.git] / arch / mips / pci / pci-bcm63xx.c
CommitLineData
e7300d04
MB
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
7 */
8
9#include <linux/types.h>
10#include <linux/pci.h>
11#include <linux/kernel.h>
12#include <linux/init.h>
19c860d9 13#include <linux/delay.h>
f2d1035e 14#include <linux/clk.h>
e7300d04
MB
15#include <asm/bootinfo.h>
16
17#include "pci-bcm63xx.h"
18
19/*
20 * Allow PCI to be disabled at runtime depending on board nvram
21 * configuration
22 */
23int bcm63xx_pci_enabled;
24
25static struct resource bcm_pci_mem_resource = {
26 .name = "bcm63xx PCI memory space",
27 .start = BCM_PCI_MEM_BASE_PA,
28 .end = BCM_PCI_MEM_END_PA,
29 .flags = IORESOURCE_MEM
30};
31
32static struct resource bcm_pci_io_resource = {
33 .name = "bcm63xx PCI IO space",
34 .start = BCM_PCI_IO_BASE_PA,
35#ifdef CONFIG_CARDBUS
36 .end = BCM_PCI_IO_HALF_PA,
37#else
38 .end = BCM_PCI_IO_END_PA,
39#endif
40 .flags = IORESOURCE_IO
41};
42
43struct pci_controller bcm63xx_controller = {
44 .pci_ops = &bcm63xx_pci_ops,
45 .io_resource = &bcm_pci_io_resource,
46 .mem_resource = &bcm_pci_mem_resource,
47};
48
49/*
50 * We handle cardbus via a fake Cardbus bridge, memory and io spaces
51 * have to be clearly separated from PCI one since we have different
52 * memory decoder.
53 */
54#ifdef CONFIG_CARDBUS
55static struct resource bcm_cb_mem_resource = {
56 .name = "bcm63xx Cardbus memory space",
57 .start = BCM_CB_MEM_BASE_PA,
58 .end = BCM_CB_MEM_END_PA,
59 .flags = IORESOURCE_MEM
60};
61
62static struct resource bcm_cb_io_resource = {
63 .name = "bcm63xx Cardbus IO space",
64 .start = BCM_PCI_IO_HALF_PA + 1,
65 .end = BCM_PCI_IO_END_PA,
66 .flags = IORESOURCE_IO
67};
68
69struct pci_controller bcm63xx_cb_controller = {
70 .pci_ops = &bcm63xx_cb_ops,
71 .io_resource = &bcm_cb_io_resource,
72 .mem_resource = &bcm_cb_mem_resource,
73};
74#endif
75
19c860d9
JG
76static struct resource bcm_pcie_mem_resource = {
77 .name = "bcm63xx PCIe memory space",
78 .start = BCM_PCIE_MEM_BASE_PA,
79 .end = BCM_PCIE_MEM_END_PA,
80 .flags = IORESOURCE_MEM,
81};
82
83static struct resource bcm_pcie_io_resource = {
84 .name = "bcm63xx PCIe IO space",
85 .start = 0,
86 .end = 0,
87 .flags = 0,
88};
89
90struct pci_controller bcm63xx_pcie_controller = {
91 .pci_ops = &bcm63xx_pcie_ops,
92 .io_resource = &bcm_pcie_io_resource,
93 .mem_resource = &bcm_pcie_mem_resource,
94};
95
e7300d04
MB
96static u32 bcm63xx_int_cfg_readl(u32 reg)
97{
98 u32 tmp;
99
100 tmp = reg & MPI_PCICFGCTL_CFGADDR_MASK;
101 tmp |= MPI_PCICFGCTL_WRITEEN_MASK;
102 bcm_mpi_writel(tmp, MPI_PCICFGCTL_REG);
103 iob();
104 return bcm_mpi_readl(MPI_PCICFGDATA_REG);
105}
106
107static void bcm63xx_int_cfg_writel(u32 val, u32 reg)
108{
109 u32 tmp;
110
111 tmp = reg & MPI_PCICFGCTL_CFGADDR_MASK;
112 tmp |= MPI_PCICFGCTL_WRITEEN_MASK;
113 bcm_mpi_writel(tmp, MPI_PCICFGCTL_REG);
114 bcm_mpi_writel(val, MPI_PCICFGDATA_REG);
115}
116
117void __iomem *pci_iospace_start;
118
19c860d9
JG
119static void __init bcm63xx_reset_pcie(void)
120{
121 u32 val;
122
19c860d9
JG
123 /* enable SERDES */
124 val = bcm_misc_readl(MISC_SERDES_CTRL_REG);
125 val |= SERDES_PCIE_EN | SERDES_PCIE_EXD_EN;
126 bcm_misc_writel(val, MISC_SERDES_CTRL_REG);
127
128 /* reset the PCIe core */
129 val = bcm_perf_readl(PERF_SOFTRESET_6328_REG);
130
131 val &= ~SOFTRESET_6328_PCIE_MASK;
132 val &= ~SOFTRESET_6328_PCIE_CORE_MASK;
133 val &= ~SOFTRESET_6328_PCIE_HARD_MASK;
134 val &= ~SOFTRESET_6328_PCIE_EXT_MASK;
135 bcm_perf_writel(val, PERF_SOFTRESET_6328_REG);
136 mdelay(10);
137
138 val |= SOFTRESET_6328_PCIE_MASK;
139 val |= SOFTRESET_6328_PCIE_CORE_MASK;
140 val |= SOFTRESET_6328_PCIE_HARD_MASK;
141 bcm_perf_writel(val, PERF_SOFTRESET_6328_REG);
142 mdelay(10);
143
144 val |= SOFTRESET_6328_PCIE_EXT_MASK;
145 bcm_perf_writel(val, PERF_SOFTRESET_6328_REG);
146 mdelay(200);
147}
148
f2d1035e
JG
149static struct clk *pcie_clk;
150
19c860d9
JG
151static int __init bcm63xx_register_pcie(void)
152{
153 u32 val;
154
f2d1035e
JG
155 /* enable clock */
156 pcie_clk = clk_get(NULL, "pcie");
157 if (IS_ERR_OR_NULL(pcie_clk))
158 return -ENODEV;
159
160 clk_prepare_enable(pcie_clk);
161
19c860d9
JG
162 bcm63xx_reset_pcie();
163
164 /* configure the PCIe bridge */
165 val = bcm_pcie_readl(PCIE_BRIDGE_OPT1_REG);
166 val |= OPT1_RD_BE_OPT_EN;
167 val |= OPT1_RD_REPLY_BE_FIX_EN;
168 val |= OPT1_PCIE_BRIDGE_HOLE_DET_EN;
169 val |= OPT1_L1_INT_STATUS_MASK_POL;
170 bcm_pcie_writel(val, PCIE_BRIDGE_OPT1_REG);
171
172 /* setup the interrupts */
173 val = bcm_pcie_readl(PCIE_BRIDGE_RC_INT_MASK_REG);
174 val |= PCIE_RC_INT_A | PCIE_RC_INT_B | PCIE_RC_INT_C | PCIE_RC_INT_D;
175 bcm_pcie_writel(val, PCIE_BRIDGE_RC_INT_MASK_REG);
176
177 val = bcm_pcie_readl(PCIE_BRIDGE_OPT2_REG);
178 /* enable credit checking and error checking */
179 val |= OPT2_TX_CREDIT_CHK_EN;
180 val |= OPT2_UBUS_UR_DECODE_DIS;
181
182 /* set device bus/func for the pcie device */
183 val |= (PCIE_BUS_DEVICE << OPT2_CFG_TYPE1_BUS_NO_SHIFT);
184 val |= OPT2_CFG_TYPE1_BD_SEL;
185 bcm_pcie_writel(val, PCIE_BRIDGE_OPT2_REG);
186
187 /* setup class code as bridge */
188 val = bcm_pcie_readl(PCIE_IDVAL3_REG);
189 val &= ~IDVAL3_CLASS_CODE_MASK;
190 val |= (PCI_CLASS_BRIDGE_PCI << IDVAL3_SUBCLASS_SHIFT);
191 bcm_pcie_writel(val, PCIE_IDVAL3_REG);
192
193 /* disable bar1 size */
194 val = bcm_pcie_readl(PCIE_CONFIG2_REG);
195 val &= ~CONFIG2_BAR1_SIZE_MASK;
196 bcm_pcie_writel(val, PCIE_CONFIG2_REG);
197
198 /* set bar0 to little endian */
199 val = (BCM_PCIE_MEM_BASE_PA >> 20) << BASEMASK_BASE_SHIFT;
200 val |= (BCM_PCIE_MEM_BASE_PA >> 20) << BASEMASK_MASK_SHIFT;
201 val |= BASEMASK_REMAP_EN;
202 bcm_pcie_writel(val, PCIE_BRIDGE_BAR0_BASEMASK_REG);
203
204 val = (BCM_PCIE_MEM_BASE_PA >> 20) << REBASE_ADDR_BASE_SHIFT;
205 bcm_pcie_writel(val, PCIE_BRIDGE_BAR0_REBASE_ADDR_REG);
206
207 register_pci_controller(&bcm63xx_pcie_controller);
208
209 return 0;
210}
211
76f42fe8 212static int __init bcm63xx_register_pci(void)
e7300d04
MB
213{
214 unsigned int mem_size;
215 u32 val;
e7300d04
MB
216 /*
217 * configuration access are done through IO space, remap 4
218 * first bytes to access it from CPU.
219 *
220 * this means that no io access from CPU should happen while
221 * we do a configuration cycle, but there's no way we can add
222 * a spinlock for each io access, so this is currently kind of
223 * broken on SMP.
224 */
225 pci_iospace_start = ioremap_nocache(BCM_PCI_IO_BASE_PA, 4);
226 if (!pci_iospace_start)
227 return -ENOMEM;
228
229 /* setup local bus to PCI access (PCI memory) */
230 val = BCM_PCI_MEM_BASE_PA & MPI_L2P_BASE_MASK;
231 bcm_mpi_writel(val, MPI_L2PMEMBASE1_REG);
232 bcm_mpi_writel(~(BCM_PCI_MEM_SIZE - 1), MPI_L2PMEMRANGE1_REG);
233 bcm_mpi_writel(val | MPI_L2PREMAP_ENABLED_MASK, MPI_L2PMEMREMAP1_REG);
234
235 /* set Cardbus IDSEL (type 0 cfg access on primary bus for
236 * this IDSEL will be done on Cardbus instead) */
237 val = bcm_pcmcia_readl(PCMCIA_C1_REG);
238 val &= ~PCMCIA_C1_CBIDSEL_MASK;
239 val |= (CARDBUS_PCI_IDSEL << PCMCIA_C1_CBIDSEL_SHIFT);
240 bcm_pcmcia_writel(val, PCMCIA_C1_REG);
241
242#ifdef CONFIG_CARDBUS
243 /* setup local bus to PCI access (Cardbus memory) */
244 val = BCM_CB_MEM_BASE_PA & MPI_L2P_BASE_MASK;
245 bcm_mpi_writel(val, MPI_L2PMEMBASE2_REG);
246 bcm_mpi_writel(~(BCM_CB_MEM_SIZE - 1), MPI_L2PMEMRANGE2_REG);
247 val |= MPI_L2PREMAP_ENABLED_MASK | MPI_L2PREMAP_IS_CARDBUS_MASK;
248 bcm_mpi_writel(val, MPI_L2PMEMREMAP2_REG);
249#else
250 /* disable second access windows */
251 bcm_mpi_writel(0, MPI_L2PMEMREMAP2_REG);
252#endif
253
254 /* setup local bus to PCI access (IO memory), we have only 1
255 * IO window for both PCI and cardbus, but it cannot handle
256 * both at the same time, assume standard PCI for now, if
257 * cardbus card has IO zone, PCI fixup will change window to
258 * cardbus */
259 val = BCM_PCI_IO_BASE_PA & MPI_L2P_BASE_MASK;
260 bcm_mpi_writel(val, MPI_L2PIOBASE_REG);
261 bcm_mpi_writel(~(BCM_PCI_IO_SIZE - 1), MPI_L2PIORANGE_REG);
262 bcm_mpi_writel(val | MPI_L2PREMAP_ENABLED_MASK, MPI_L2PIOREMAP_REG);
263
264 /* enable PCI related GPIO pins */
265 bcm_mpi_writel(MPI_LOCBUSCTL_EN_PCI_GPIO_MASK, MPI_LOCBUSCTL_REG);
266
267 /* setup PCI to local bus access, used by PCI device to target
268 * local RAM while bus mastering */
269 bcm63xx_int_cfg_writel(0, PCI_BASE_ADDRESS_3);
04712f3f 270 if (BCMCPU_IS_6358() || BCMCPU_IS_6368())
e7300d04
MB
271 val = MPI_SP0_REMAP_ENABLE_MASK;
272 else
273 val = 0;
274 bcm_mpi_writel(val, MPI_SP0_REMAP_REG);
275
276 bcm63xx_int_cfg_writel(0x0, PCI_BASE_ADDRESS_4);
277 bcm_mpi_writel(0, MPI_SP1_REMAP_REG);
278
279 mem_size = bcm63xx_get_memory_size();
280
281 /* 6348 before rev b0 exposes only 16 MB of RAM memory through
282 * PCI, throw a warning if we have more memory */
283 if (BCMCPU_IS_6348() && (bcm63xx_get_cpu_rev() & 0xf0) == 0xa0) {
284 if (mem_size > (16 * 1024 * 1024))
285 printk(KERN_WARNING "bcm63xx: this CPU "
286 "revision cannot handle more than 16MB "
287 "of RAM for PCI bus mastering\n");
288 } else {
289 /* setup sp0 range to local RAM size */
290 bcm_mpi_writel(~(mem_size - 1), MPI_SP0_RANGE_REG);
291 bcm_mpi_writel(0, MPI_SP1_RANGE_REG);
292 }
293
294 /* change host bridge retry counter to infinite number of
295 * retry, needed for some broadcom wifi cards with Silicon
296 * Backplane bus where access to srom seems very slow */
297 val = bcm63xx_int_cfg_readl(BCMPCI_REG_TIMERS);
298 val &= ~REG_TIMER_RETRY_MASK;
299 bcm63xx_int_cfg_writel(val, BCMPCI_REG_TIMERS);
300
301 /* enable memory decoder and bus mastering */
302 val = bcm63xx_int_cfg_readl(PCI_COMMAND);
303 val |= (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
304 bcm63xx_int_cfg_writel(val, PCI_COMMAND);
305
306 /* enable read prefetching & disable byte swapping for bus
307 * mastering transfers */
308 val = bcm_mpi_readl(MPI_PCIMODESEL_REG);
309 val &= ~MPI_PCIMODESEL_BAR1_NOSWAP_MASK;
310 val &= ~MPI_PCIMODESEL_BAR2_NOSWAP_MASK;
311 val &= ~MPI_PCIMODESEL_PREFETCH_MASK;
312 val |= (8 << MPI_PCIMODESEL_PREFETCH_SHIFT);
313 bcm_mpi_writel(val, MPI_PCIMODESEL_REG);
314
315 /* enable pci interrupt */
316 val = bcm_mpi_readl(MPI_LOCINT_REG);
317 val |= MPI_LOCINT_MASK(MPI_LOCINT_EXT_PCI_INT);
318 bcm_mpi_writel(val, MPI_LOCINT_REG);
319
320 register_pci_controller(&bcm63xx_controller);
321
322#ifdef CONFIG_CARDBUS
323 register_pci_controller(&bcm63xx_cb_controller);
324#endif
325
326 /* mark memory space used for IO mapping as reserved */
327 request_mem_region(BCM_PCI_IO_BASE_PA, BCM_PCI_IO_SIZE,
328 "bcm63xx PCI IO space");
329 return 0;
330}
331
76f42fe8
JG
332
333static int __init bcm63xx_pci_init(void)
334{
335 if (!bcm63xx_pci_enabled)
336 return -ENODEV;
337
338 switch (bcm63xx_get_cpu_id()) {
19c860d9
JG
339 case BCM6328_CPU_ID:
340 return bcm63xx_register_pcie();
76f42fe8
JG
341 case BCM6348_CPU_ID:
342 case BCM6358_CPU_ID:
343 case BCM6368_CPU_ID:
344 return bcm63xx_register_pci();
345 default:
346 return -ENODEV;
347 }
348}
349
e7300d04 350arch_initcall(bcm63xx_pci_init);
This page took 0.318292 seconds and 5 git commands to generate.