Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
pci-bcm63xx.c
Go to the documentation of this file.
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 <[email protected]>
7  */
8 
9 #include <linux/types.h>
10 #include <linux/pci.h>
11 #include <linux/kernel.h>
12 #include <linux/init.h>
13 #include <linux/delay.h>
14 #include <asm/bootinfo.h>
15 
16 #include "pci-bcm63xx.h"
17 
18 /*
19  * Allow PCI to be disabled at runtime depending on board nvram
20  * configuration
21  */
23 
24 static struct resource bcm_pci_mem_resource = {
25  .name = "bcm63xx PCI memory space",
26  .start = BCM_PCI_MEM_BASE_PA,
27  .end = BCM_PCI_MEM_END_PA,
28  .flags = IORESOURCE_MEM
29 };
30 
31 static struct resource bcm_pci_io_resource = {
32  .name = "bcm63xx PCI IO space",
33  .start = BCM_PCI_IO_BASE_PA,
34 #ifdef CONFIG_CARDBUS
35  .end = BCM_PCI_IO_HALF_PA,
36 #else
37  .end = BCM_PCI_IO_END_PA,
38 #endif
39  .flags = IORESOURCE_IO
40 };
41 
43  .pci_ops = &bcm63xx_pci_ops,
44  .io_resource = &bcm_pci_io_resource,
45  .mem_resource = &bcm_pci_mem_resource,
46 };
47 
48 /*
49  * We handle cardbus via a fake Cardbus bridge, memory and io spaces
50  * have to be clearly separated from PCI one since we have different
51  * memory decoder.
52  */
53 #ifdef CONFIG_CARDBUS
54 static struct resource bcm_cb_mem_resource = {
55  .name = "bcm63xx Cardbus memory space",
56  .start = BCM_CB_MEM_BASE_PA,
57  .end = BCM_CB_MEM_END_PA,
58  .flags = IORESOURCE_MEM
59 };
60 
61 static struct resource bcm_cb_io_resource = {
62  .name = "bcm63xx Cardbus IO space",
63  .start = BCM_PCI_IO_HALF_PA + 1,
64  .end = BCM_PCI_IO_END_PA,
65  .flags = IORESOURCE_IO
66 };
67 
68 struct pci_controller bcm63xx_cb_controller = {
69  .pci_ops = &bcm63xx_cb_ops,
70  .io_resource = &bcm_cb_io_resource,
71  .mem_resource = &bcm_cb_mem_resource,
72 };
73 #endif
74 
75 static struct resource bcm_pcie_mem_resource = {
76  .name = "bcm63xx PCIe memory space",
77  .start = BCM_PCIE_MEM_BASE_PA,
78  .end = BCM_PCIE_MEM_END_PA,
79  .flags = IORESOURCE_MEM,
80 };
81 
82 static struct resource bcm_pcie_io_resource = {
83  .name = "bcm63xx PCIe IO space",
84  .start = 0,
85  .end = 0,
86  .flags = 0,
87 };
88 
90  .pci_ops = &bcm63xx_pcie_ops,
91  .io_resource = &bcm_pcie_io_resource,
92  .mem_resource = &bcm_pcie_mem_resource,
93 };
94 
95 static u32 bcm63xx_int_cfg_readl(u32 reg)
96 {
97  u32 tmp;
98 
99  tmp = reg & MPI_PCICFGCTL_CFGADDR_MASK;
102  iob();
104 }
105 
106 static void bcm63xx_int_cfg_writel(u32 val, u32 reg)
107 {
108  u32 tmp;
109 
110  tmp = reg & MPI_PCICFGCTL_CFGADDR_MASK;
114 }
115 
117 
118 static void __init bcm63xx_reset_pcie(void)
119 {
120  u32 val;
121 
122  /* enable clock */
124  val |= CKCTL_6328_PCIE_EN;
126 
127  /* enable SERDES */
131 
132  /* reset the PCIe core */
134 
135  val &= ~SOFTRESET_6328_PCIE_MASK;
140  mdelay(10);
141 
146  mdelay(10);
147 
150  mdelay(200);
151 }
152 
153 static int __init bcm63xx_register_pcie(void)
154 {
155  u32 val;
156 
157  bcm63xx_reset_pcie();
158 
159  /* configure the PCIe bridge */
161  val |= OPT1_RD_BE_OPT_EN;
166 
167  /* setup the interrupts */
171 
173  /* enable credit checking and error checking */
174  val |= OPT2_TX_CREDIT_CHK_EN;
176 
177  /* set device bus/func for the pcie device */
179  val |= OPT2_CFG_TYPE1_BD_SEL;
181 
182  /* setup class code as bridge */
184  val &= ~IDVAL3_CLASS_CODE_MASK;
187 
188  /* disable bar1 size */
190  val &= ~CONFIG2_BAR1_SIZE_MASK;
192 
193  /* set bar0 to little endian */
194  val = (BCM_PCIE_MEM_BASE_PA >> 20) << BASEMASK_BASE_SHIFT;
195  val |= (BCM_PCIE_MEM_BASE_PA >> 20) << BASEMASK_MASK_SHIFT;
196  val |= BASEMASK_REMAP_EN;
198 
201 
202  register_pci_controller(&bcm63xx_pcie_controller);
203 
204  return 0;
205 }
206 
207 static int __init bcm63xx_register_pci(void)
208 {
209  unsigned int mem_size;
210  u32 val;
211  /*
212  * configuration access are done through IO space, remap 4
213  * first bytes to access it from CPU.
214  *
215  * this means that no io access from CPU should happen while
216  * we do a configuration cycle, but there's no way we can add
217  * a spinlock for each io access, so this is currently kind of
218  * broken on SMP.
219  */
221  if (!pci_iospace_start)
222  return -ENOMEM;
223 
224  /* setup local bus to PCI access (PCI memory) */
229 
230  /* set Cardbus IDSEL (type 0 cfg access on primary bus for
231  * this IDSEL will be done on Cardbus instead) */
233  val &= ~PCMCIA_C1_CBIDSEL_MASK;
236 
237 #ifdef CONFIG_CARDBUS
238  /* setup local bus to PCI access (Cardbus memory) */
244 #else
245  /* disable second access windows */
247 #endif
248 
249  /* setup local bus to PCI access (IO memory), we have only 1
250  * IO window for both PCI and cardbus, but it cannot handle
251  * both at the same time, assume standard PCI for now, if
252  * cardbus card has IO zone, PCI fixup will change window to
253  * cardbus */
258 
259  /* enable PCI related GPIO pins */
261 
262  /* setup PCI to local bus access, used by PCI device to target
263  * local RAM while bus mastering */
264  bcm63xx_int_cfg_writel(0, PCI_BASE_ADDRESS_3);
265  if (BCMCPU_IS_6358() || BCMCPU_IS_6368())
267  else
268  val = 0;
270 
271  bcm63xx_int_cfg_writel(0x0, PCI_BASE_ADDRESS_4);
273 
274  mem_size = bcm63xx_get_memory_size();
275 
276  /* 6348 before rev b0 exposes only 16 MB of RAM memory through
277  * PCI, throw a warning if we have more memory */
278  if (BCMCPU_IS_6348() && (bcm63xx_get_cpu_rev() & 0xf0) == 0xa0) {
279  if (mem_size > (16 * 1024 * 1024))
280  printk(KERN_WARNING "bcm63xx: this CPU "
281  "revision cannot handle more than 16MB "
282  "of RAM for PCI bus mastering\n");
283  } else {
284  /* setup sp0 range to local RAM size */
285  bcm_mpi_writel(~(mem_size - 1), MPI_SP0_RANGE_REG);
287  }
288 
289  /* change host bridge retry counter to infinite number of
290  * retry, needed for some broadcom wifi cards with Silicon
291  * Backplane bus where access to srom seems very slow */
292  val = bcm63xx_int_cfg_readl(BCMPCI_REG_TIMERS);
293  val &= ~REG_TIMER_RETRY_MASK;
294  bcm63xx_int_cfg_writel(val, BCMPCI_REG_TIMERS);
295 
296  /* enable memory decoder and bus mastering */
297  val = bcm63xx_int_cfg_readl(PCI_COMMAND);
299  bcm63xx_int_cfg_writel(val, PCI_COMMAND);
300 
301  /* enable read prefetching & disable byte swapping for bus
302  * mastering transfers */
307  val |= (8 << MPI_PCIMODESEL_PREFETCH_SHIFT);
309 
310  /* enable pci interrupt */
314 
315  register_pci_controller(&bcm63xx_controller);
316 
317 #ifdef CONFIG_CARDBUS
318  register_pci_controller(&bcm63xx_cb_controller);
319 #endif
320 
321  /* mark memory space used for IO mapping as reserved */
323  "bcm63xx PCI IO space");
324  return 0;
325 }
326 
327 
328 static int __init bcm63xx_pci_init(void)
329 {
330  if (!bcm63xx_pci_enabled)
331  return -ENODEV;
332 
333  switch (bcm63xx_get_cpu_id()) {
334  case BCM6328_CPU_ID:
335  return bcm63xx_register_pcie();
336  case BCM6348_CPU_ID:
337  case BCM6358_CPU_ID:
338  case BCM6368_CPU_ID:
339  return bcm63xx_register_pci();
340  default:
341  return -ENODEV;
342  }
343 }
344 
345 arch_initcall(bcm63xx_pci_init);