Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
driver_pci.c
Go to the documentation of this file.
1 /*
2  * Broadcom specific AMBA
3  * PCI Core
4  *
5  * Copyright 2005, 2011, Broadcom Corporation
6  * Copyright 2006, 2007, Michael Buesch <[email protected]>
7  * Copyright 2011, 2012, Hauke Mehrtens <[email protected]>
8  *
9  * Licensed under the GNU/GPL. See COPYING for details.
10  */
11 
12 #include "bcma_private.h"
13 #include <linux/export.h>
14 #include <linux/bcma/bcma.h>
15 
16 /**************************************************
17  * R/W ops.
18  **************************************************/
19 
21 {
25 }
26 
27 static void bcma_pcie_write(struct bcma_drv_pci *pc, u32 address, u32 data)
28 {
32 }
33 
34 static void bcma_pcie_mdio_set_phy(struct bcma_drv_pci *pc, u8 phy)
35 {
36  u32 v;
37  int i;
38 
46  v |= (phy << 4);
48 
49  udelay(10);
50  for (i = 0; i < 200; i++) {
53  break;
54  usleep_range(1000, 2000);
55  }
56 }
57 
58 static u16 bcma_pcie_mdio_read(struct bcma_drv_pci *pc, u8 device, u8 address)
59 {
60  int max_retries = 10;
61  u16 ret = 0;
62  u32 v;
63  int i;
64 
65  /* enable mdio access to SERDES */
69 
70  if (pc->core->id.rev >= 10) {
71  max_retries = 200;
72  bcma_pcie_mdio_set_phy(pc, device);
75  v |= (address << BCMA_CORE_PCI_MDIODATA_REGADDR_SHF);
76  } else {
79  }
80 
84 
86  /* Wait for the device to complete the transaction */
87  udelay(10);
88  for (i = 0; i < max_retries; i++) {
91  udelay(10);
93  break;
94  }
95  usleep_range(1000, 2000);
96  }
98  return ret;
99 }
100 
101 static void bcma_pcie_mdio_write(struct bcma_drv_pci *pc, u8 device,
102  u8 address, u16 data)
103 {
104  int max_retries = 10;
105  u32 v;
106  int i;
107 
108  /* enable mdio access to SERDES */
112 
113  if (pc->core->id.rev >= 10) {
114  max_retries = 200;
115  bcma_pcie_mdio_set_phy(pc, device);
118  v |= (address << BCMA_CORE_PCI_MDIODATA_REGADDR_SHF);
119  } else {
121  v |= (address << BCMA_CORE_PCI_MDIODATA_REGADDR_SHF_OLD);
122  }
123 
127  v |= data;
129  /* Wait for the device to complete the transaction */
130  udelay(10);
131  for (i = 0; i < max_retries; i++) {
134  break;
135  usleep_range(1000, 2000);
136  }
138 }
139 
140 /**************************************************
141  * Workarounds.
142  **************************************************/
143 
144 static u8 bcma_pcicore_polarity_workaround(struct bcma_drv_pci *pc)
145 {
146  u32 tmp;
147 
152  else
154 }
155 
156 static void bcma_pcicore_serdes_workaround(struct bcma_drv_pci *pc)
157 {
158  u16 tmp;
159 
160  bcma_pcie_mdio_write(pc, BCMA_CORE_PCI_MDIODATA_DEV_RX,
162  bcma_pcicore_polarity_workaround(pc));
163  tmp = bcma_pcie_mdio_read(pc, BCMA_CORE_PCI_MDIODATA_DEV_PLL,
166  bcma_pcie_mdio_write(pc, BCMA_CORE_PCI_MDIODATA_DEV_PLL,
168  tmp & ~BCMA_CORE_PCI_PLL_CTRL_FREQDET_EN);
169 }
170 
171 static void bcma_core_pci_fixcfg(struct bcma_drv_pci *pc)
172 {
173  struct bcma_device *core = pc->core;
174  u16 val16, core_index;
175  uint regoff;
176 
178  core_index = (u16)core->core_index;
179 
180  val16 = pcicore_read16(pc, regoff);
182  != core_index) {
183  val16 = (core_index << BCMA_CORE_PCI_SPROM_PI_SHIFT) |
184  (val16 & ~BCMA_CORE_PCI_SPROM_PI_MASK);
185  pcicore_write16(pc, regoff, val16);
186  }
187 }
188 
189 /* Fix MISC config to allow coming out of L2/L3-Ready state w/o PRST */
190 /* Needs to happen when coming out of 'standby'/'hibernate' */
191 static void bcma_core_pci_config_fixup(struct bcma_drv_pci *pc)
192 {
193  u16 val16;
194  uint regoff;
195 
197 
198  val16 = pcicore_read16(pc, regoff);
199 
202  pcicore_write16(pc, regoff, val16);
203  }
204 }
205 
206 /**************************************************
207  * Init.
208  **************************************************/
209 
210 static void __devinit bcma_core_pci_clientmode_init(struct bcma_drv_pci *pc)
211 {
212  bcma_core_pci_fixcfg(pc);
213  bcma_pcicore_serdes_workaround(pc);
214  bcma_core_pci_config_fixup(pc);
215 }
216 
218 {
219  if (pc->setup_done)
220  return;
221 
222 #ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE
224  if (pc->hostmode)
226 #endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */
227 
228  if (!pc->hostmode)
229  bcma_core_pci_clientmode_init(pc);
230 }
231 
232 int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core,
233  bool enable)
234 {
235  struct pci_dev *pdev;
236  u32 coremask, tmp;
237  int err = 0;
238 
239  if (!pc || core->bus->hosttype != BCMA_HOSTTYPE_PCI) {
240  /* This bcma device is not on a PCI host-bus. So the IRQs are
241  * not routed through the PCI core.
242  * So we must not enable routing through the PCI core. */
243  goto out;
244  }
245 
246  pdev = pc->core->bus->host_pci;
247 
248  err = pci_read_config_dword(pdev, BCMA_PCI_IRQMASK, &tmp);
249  if (err)
250  goto out;
251 
252  coremask = BIT(core->core_index) << 8;
253  if (enable)
254  tmp |= coremask;
255  else
256  tmp &= ~coremask;
257 
258  err = pci_write_config_dword(pdev, BCMA_PCI_IRQMASK, tmp);
259 
260 out:
261  return err;
262 }
264 
265 void bcma_core_pci_extend_L1timer(struct bcma_drv_pci *pc, bool extend)
266 {
267  u32 w;
268 
270  if (extend)
272  else
274  bcma_pcie_write(pc, BCMA_CORE_PCI_DLLP_PMTHRESHREG, w);
276 }