Branch data Line data Source code
1 : : /*
2 : : * Sonics Silicon Backplane
3 : : * Broadcom PCI-core driver
4 : : *
5 : : * Copyright 2005, Broadcom Corporation
6 : : * Copyright 2006, 2007, Michael Buesch <m@bues.ch>
7 : : *
8 : : * Licensed under the GNU/GPL. See COPYING for details.
9 : : */
10 : :
11 : : #include "ssb_private.h"
12 : :
13 : : #include <linux/ssb/ssb.h>
14 : : #include <linux/pci.h>
15 : : #include <linux/export.h>
16 : : #include <linux/delay.h>
17 : : #include <linux/ssb/ssb_embedded.h>
18 : :
19 : : static u32 ssb_pcie_read(struct ssb_pcicore *pc, u32 address);
20 : : static void ssb_pcie_write(struct ssb_pcicore *pc, u32 address, u32 data);
21 : : static u16 ssb_pcie_mdio_read(struct ssb_pcicore *pc, u8 device, u8 address);
22 : : static void ssb_pcie_mdio_write(struct ssb_pcicore *pc, u8 device,
23 : : u8 address, u16 data);
24 : :
25 : : static inline
26 : 0 : u32 pcicore_read32(struct ssb_pcicore *pc, u16 offset)
27 : : {
28 : 0 : return ssb_read32(pc->dev, offset);
29 : : }
30 : :
31 : : static inline
32 : 0 : void pcicore_write32(struct ssb_pcicore *pc, u16 offset, u32 value)
33 : : {
34 : 0 : ssb_write32(pc->dev, offset, value);
35 : : }
36 : :
37 : : static inline
38 : 0 : u16 pcicore_read16(struct ssb_pcicore *pc, u16 offset)
39 : : {
40 : 0 : return ssb_read16(pc->dev, offset);
41 : : }
42 : :
43 : : static inline
44 : 0 : void pcicore_write16(struct ssb_pcicore *pc, u16 offset, u16 value)
45 : : {
46 : 0 : ssb_write16(pc->dev, offset, value);
47 : 0 : }
48 : :
49 : : /**************************************************
50 : : * Code for hostmode operation.
51 : : **************************************************/
52 : :
53 : : #ifdef CONFIG_SSB_PCICORE_HOSTMODE
54 : :
55 : : #include <asm/paccess.h>
56 : : /* Probe a 32bit value on the bus and catch bus exceptions.
57 : : * Returns nonzero on a bus exception.
58 : : * This is MIPS specific */
59 : : #define mips_busprobe32(val, addr) get_dbe((val), ((u32 *)(addr)))
60 : :
61 : : /* Assume one-hot slot wiring */
62 : : #define SSB_PCI_SLOT_MAX 16
63 : :
64 : : /* Global lock is OK, as we won't have more than one extpci anyway. */
65 : : static DEFINE_SPINLOCK(cfgspace_lock);
66 : : /* Core to access the external PCI config space. Can only have one. */
67 : : static struct ssb_pcicore *extpci_core;
68 : :
69 : :
70 : : static u32 get_cfgspace_addr(struct ssb_pcicore *pc,
71 : : unsigned int bus, unsigned int dev,
72 : : unsigned int func, unsigned int off)
73 : : {
74 : : u32 addr = 0;
75 : : u32 tmp;
76 : :
77 : : /* We do only have one cardbus device behind the bridge. */
78 : : if (pc->cardbusmode && (dev > 1))
79 : : goto out;
80 : :
81 : : if (bus == 0) {
82 : : /* Type 0 transaction */
83 : : if (unlikely(dev >= SSB_PCI_SLOT_MAX))
84 : : goto out;
85 : : /* Slide the window */
86 : : tmp = SSB_PCICORE_SBTOPCI_CFG0;
87 : : tmp |= ((1 << (dev + 16)) & SSB_PCICORE_SBTOPCI1_MASK);
88 : : pcicore_write32(pc, SSB_PCICORE_SBTOPCI1, tmp);
89 : : /* Calculate the address */
90 : : addr = SSB_PCI_CFG;
91 : : addr |= ((1 << (dev + 16)) & ~SSB_PCICORE_SBTOPCI1_MASK);
92 : : addr |= (func << 8);
93 : : addr |= (off & ~3);
94 : : } else {
95 : : /* Type 1 transaction */
96 : : pcicore_write32(pc, SSB_PCICORE_SBTOPCI1,
97 : : SSB_PCICORE_SBTOPCI_CFG1);
98 : : /* Calculate the address */
99 : : addr = SSB_PCI_CFG;
100 : : addr |= (bus << 16);
101 : : addr |= (dev << 11);
102 : : addr |= (func << 8);
103 : : addr |= (off & ~3);
104 : : }
105 : : out:
106 : : return addr;
107 : : }
108 : :
109 : : static int ssb_extpci_read_config(struct ssb_pcicore *pc,
110 : : unsigned int bus, unsigned int dev,
111 : : unsigned int func, unsigned int off,
112 : : void *buf, int len)
113 : : {
114 : : int err = -EINVAL;
115 : : u32 addr, val;
116 : : void __iomem *mmio;
117 : :
118 : : WARN_ON(!pc->hostmode);
119 : : if (unlikely(len != 1 && len != 2 && len != 4))
120 : : goto out;
121 : : addr = get_cfgspace_addr(pc, bus, dev, func, off);
122 : : if (unlikely(!addr))
123 : : goto out;
124 : : err = -ENOMEM;
125 : : mmio = ioremap(addr, len);
126 : : if (!mmio)
127 : : goto out;
128 : :
129 : : if (mips_busprobe32(val, mmio)) {
130 : : val = 0xffffffff;
131 : : goto unmap;
132 : : }
133 : :
134 : : val = readl(mmio);
135 : : val >>= (8 * (off & 3));
136 : :
137 : : switch (len) {
138 : : case 1:
139 : : *((u8 *)buf) = (u8)val;
140 : : break;
141 : : case 2:
142 : : *((u16 *)buf) = (u16)val;
143 : : break;
144 : : case 4:
145 : : *((u32 *)buf) = (u32)val;
146 : : break;
147 : : }
148 : : err = 0;
149 : : unmap:
150 : : iounmap(mmio);
151 : : out:
152 : : return err;
153 : : }
154 : :
155 : : static int ssb_extpci_write_config(struct ssb_pcicore *pc,
156 : : unsigned int bus, unsigned int dev,
157 : : unsigned int func, unsigned int off,
158 : : const void *buf, int len)
159 : : {
160 : : int err = -EINVAL;
161 : : u32 addr, val = 0;
162 : : void __iomem *mmio;
163 : :
164 : : WARN_ON(!pc->hostmode);
165 : : if (unlikely(len != 1 && len != 2 && len != 4))
166 : : goto out;
167 : : addr = get_cfgspace_addr(pc, bus, dev, func, off);
168 : : if (unlikely(!addr))
169 : : goto out;
170 : : err = -ENOMEM;
171 : : mmio = ioremap(addr, len);
172 : : if (!mmio)
173 : : goto out;
174 : :
175 : : if (mips_busprobe32(val, mmio)) {
176 : : val = 0xffffffff;
177 : : goto unmap;
178 : : }
179 : :
180 : : switch (len) {
181 : : case 1:
182 : : val = readl(mmio);
183 : : val &= ~(0xFF << (8 * (off & 3)));
184 : : val |= *((const u8 *)buf) << (8 * (off & 3));
185 : : break;
186 : : case 2:
187 : : val = readl(mmio);
188 : : val &= ~(0xFFFF << (8 * (off & 3)));
189 : : val |= *((const u16 *)buf) << (8 * (off & 3));
190 : : break;
191 : : case 4:
192 : : val = *((const u32 *)buf);
193 : : break;
194 : : }
195 : : writel(val, mmio);
196 : :
197 : : err = 0;
198 : : unmap:
199 : : iounmap(mmio);
200 : : out:
201 : : return err;
202 : : }
203 : :
204 : : static int ssb_pcicore_read_config(struct pci_bus *bus, unsigned int devfn,
205 : : int reg, int size, u32 *val)
206 : : {
207 : : unsigned long flags;
208 : : int err;
209 : :
210 : : spin_lock_irqsave(&cfgspace_lock, flags);
211 : : err = ssb_extpci_read_config(extpci_core, bus->number, PCI_SLOT(devfn),
212 : : PCI_FUNC(devfn), reg, val, size);
213 : : spin_unlock_irqrestore(&cfgspace_lock, flags);
214 : :
215 : : return err ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
216 : : }
217 : :
218 : : static int ssb_pcicore_write_config(struct pci_bus *bus, unsigned int devfn,
219 : : int reg, int size, u32 val)
220 : : {
221 : : unsigned long flags;
222 : : int err;
223 : :
224 : : spin_lock_irqsave(&cfgspace_lock, flags);
225 : : err = ssb_extpci_write_config(extpci_core, bus->number, PCI_SLOT(devfn),
226 : : PCI_FUNC(devfn), reg, &val, size);
227 : : spin_unlock_irqrestore(&cfgspace_lock, flags);
228 : :
229 : : return err ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
230 : : }
231 : :
232 : : static struct pci_ops ssb_pcicore_pciops = {
233 : : .read = ssb_pcicore_read_config,
234 : : .write = ssb_pcicore_write_config,
235 : : };
236 : :
237 : : static struct resource ssb_pcicore_mem_resource = {
238 : : .name = "SSB PCIcore external memory",
239 : : .start = SSB_PCI_DMA,
240 : : .end = SSB_PCI_DMA + SSB_PCI_DMA_SZ - 1,
241 : : .flags = IORESOURCE_MEM | IORESOURCE_PCI_FIXED,
242 : : };
243 : :
244 : : static struct resource ssb_pcicore_io_resource = {
245 : : .name = "SSB PCIcore external I/O",
246 : : .start = 0x100,
247 : : .end = 0x7FF,
248 : : .flags = IORESOURCE_IO | IORESOURCE_PCI_FIXED,
249 : : };
250 : :
251 : : static struct pci_controller ssb_pcicore_controller = {
252 : : .pci_ops = &ssb_pcicore_pciops,
253 : : .io_resource = &ssb_pcicore_io_resource,
254 : : .mem_resource = &ssb_pcicore_mem_resource,
255 : : };
256 : :
257 : : /* This function is called when doing a pci_enable_device().
258 : : * We must first check if the device is a device on the PCI-core bridge. */
259 : : int ssb_pcicore_plat_dev_init(struct pci_dev *d)
260 : : {
261 : : if (d->bus->ops != &ssb_pcicore_pciops) {
262 : : /* This is not a device on the PCI-core bridge. */
263 : : return -ENODEV;
264 : : }
265 : :
266 : : dev_info(&d->dev, "PCI: Fixing up device %s\n", pci_name(d));
267 : :
268 : : /* Fix up interrupt lines */
269 : : d->irq = ssb_mips_irq(extpci_core->dev) + 2;
270 : : pci_write_config_byte(d, PCI_INTERRUPT_LINE, d->irq);
271 : :
272 : : return 0;
273 : : }
274 : :
275 : : /* Early PCI fixup for a device on the PCI-core bridge. */
276 : : static void ssb_pcicore_fixup_pcibridge(struct pci_dev *dev)
277 : : {
278 : : u8 lat;
279 : :
280 : : if (dev->bus->ops != &ssb_pcicore_pciops) {
281 : : /* This is not a device on the PCI-core bridge. */
282 : : return;
283 : : }
284 : : if (dev->bus->number != 0 || PCI_SLOT(dev->devfn) != 0)
285 : : return;
286 : :
287 : : dev_info(&dev->dev, "PCI: Fixing up bridge %s\n", pci_name(dev));
288 : :
289 : : /* Enable PCI bridge bus mastering and memory space */
290 : : pci_set_master(dev);
291 : : if (pcibios_enable_device(dev, ~0) < 0) {
292 : : dev_err(&dev->dev, "PCI: SSB bridge enable failed\n");
293 : : return;
294 : : }
295 : :
296 : : /* Enable PCI bridge BAR1 prefetch and burst */
297 : : pci_write_config_dword(dev, SSB_BAR1_CONTROL, 3);
298 : :
299 : : /* Make sure our latency is high enough to handle the devices behind us */
300 : : lat = 168;
301 : : dev_info(&dev->dev,
302 : : "PCI: Fixing latency timer of device %s to %u\n",
303 : : pci_name(dev), lat);
304 : : pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
305 : : }
306 : : DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, ssb_pcicore_fixup_pcibridge);
307 : :
308 : : /* PCI device IRQ mapping. */
309 : : int ssb_pcicore_pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
310 : : {
311 : : if (dev->bus->ops != &ssb_pcicore_pciops) {
312 : : /* This is not a device on the PCI-core bridge. */
313 : : return -ENODEV;
314 : : }
315 : : return ssb_mips_irq(extpci_core->dev) + 2;
316 : : }
317 : :
318 : : static void ssb_pcicore_init_hostmode(struct ssb_pcicore *pc)
319 : : {
320 : : u32 val;
321 : :
322 : : if (WARN_ON(extpci_core))
323 : : return;
324 : : extpci_core = pc;
325 : :
326 : : dev_dbg(pc->dev->dev, "PCIcore in host mode found\n");
327 : : /* Reset devices on the external PCI bus */
328 : : val = SSB_PCICORE_CTL_RST_OE;
329 : : val |= SSB_PCICORE_CTL_CLK_OE;
330 : : pcicore_write32(pc, SSB_PCICORE_CTL, val);
331 : : val |= SSB_PCICORE_CTL_CLK; /* Clock on */
332 : : pcicore_write32(pc, SSB_PCICORE_CTL, val);
333 : : udelay(150); /* Assertion time demanded by the PCI standard */
334 : : val |= SSB_PCICORE_CTL_RST; /* Deassert RST# */
335 : : pcicore_write32(pc, SSB_PCICORE_CTL, val);
336 : : val = SSB_PCICORE_ARBCTL_INTERN;
337 : : pcicore_write32(pc, SSB_PCICORE_ARBCTL, val);
338 : : udelay(1); /* Assertion time demanded by the PCI standard */
339 : :
340 : : if (pc->dev->bus->has_cardbus_slot) {
341 : : dev_dbg(pc->dev->dev, "CardBus slot detected\n");
342 : : pc->cardbusmode = 1;
343 : : /* GPIO 1 resets the bridge */
344 : : ssb_gpio_out(pc->dev->bus, 1, 1);
345 : : ssb_gpio_outen(pc->dev->bus, 1, 1);
346 : : pcicore_write16(pc, SSB_PCICORE_SPROM(0),
347 : : pcicore_read16(pc, SSB_PCICORE_SPROM(0))
348 : : | 0x0400);
349 : : }
350 : :
351 : : /* 64MB I/O window */
352 : : pcicore_write32(pc, SSB_PCICORE_SBTOPCI0,
353 : : SSB_PCICORE_SBTOPCI_IO);
354 : : /* 64MB config space */
355 : : pcicore_write32(pc, SSB_PCICORE_SBTOPCI1,
356 : : SSB_PCICORE_SBTOPCI_CFG0);
357 : : /* 1GB memory window */
358 : : pcicore_write32(pc, SSB_PCICORE_SBTOPCI2,
359 : : SSB_PCICORE_SBTOPCI_MEM | SSB_PCI_DMA);
360 : :
361 : : /*
362 : : * Accessing PCI config without a proper delay after devices reset (not
363 : : * GPIO reset) was causing reboots on WRT300N v1.0 (BCM4704).
364 : : * Tested delay 850 us lowered reboot chance to 50-80%, 1000 us fixed it
365 : : * completely. Flushing all writes was also tested but with no luck.
366 : : * The same problem was reported for WRT350N v1 (BCM4705), so we just
367 : : * sleep here unconditionally.
368 : : */
369 : : usleep_range(1000, 2000);
370 : :
371 : : /* Enable PCI bridge BAR0 prefetch and burst */
372 : : val = PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
373 : : ssb_extpci_write_config(pc, 0, 0, 0, PCI_COMMAND, &val, 2);
374 : : /* Clear error conditions */
375 : : val = 0;
376 : : ssb_extpci_write_config(pc, 0, 0, 0, PCI_STATUS, &val, 2);
377 : :
378 : : /* Enable PCI interrupts */
379 : : pcicore_write32(pc, SSB_PCICORE_IMASK,
380 : : SSB_PCICORE_IMASK_INTA);
381 : :
382 : : /* Ok, ready to run, register it to the system.
383 : : * The following needs change, if we want to port hostmode
384 : : * to non-MIPS platform. */
385 : : ssb_pcicore_controller.io_map_base = (unsigned long)ioremap(SSB_PCI_MEM, 0x04000000);
386 : : set_io_port_base(ssb_pcicore_controller.io_map_base);
387 : : /* Give some time to the PCI controller to configure itself with the new
388 : : * values. Not waiting at this point causes crashes of the machine. */
389 : : mdelay(10);
390 : : register_pci_controller(&ssb_pcicore_controller);
391 : : }
392 : :
393 : : static int pcicore_is_in_hostmode(struct ssb_pcicore *pc)
394 : : {
395 : : struct ssb_bus *bus = pc->dev->bus;
396 : : u16 chipid_top;
397 : : u32 tmp;
398 : :
399 : : chipid_top = (bus->chip_id & 0xFF00);
400 : : if (chipid_top != 0x4700 &&
401 : : chipid_top != 0x5300)
402 : : return 0;
403 : :
404 : : if (bus->sprom.boardflags_lo & SSB_PCICORE_BFL_NOPCI)
405 : : return 0;
406 : :
407 : : /* The 200-pin BCM4712 package does not bond out PCI. Even when
408 : : * PCI is bonded out, some boards may leave the pins floating. */
409 : : if (bus->chip_id == 0x4712) {
410 : : if (bus->chip_package == SSB_CHIPPACK_BCM4712S)
411 : : return 0;
412 : : if (bus->chip_package == SSB_CHIPPACK_BCM4712M)
413 : : return 0;
414 : : }
415 : : if (bus->chip_id == 0x5350)
416 : : return 0;
417 : :
418 : : return !mips_busprobe32(tmp, (bus->mmio + (pc->dev->core_index * SSB_CORE_SIZE)));
419 : : }
420 : : #endif /* CONFIG_SSB_PCICORE_HOSTMODE */
421 : :
422 : : /**************************************************
423 : : * Workarounds.
424 : : **************************************************/
425 : :
426 : : static void ssb_pcicore_fix_sprom_core_index(struct ssb_pcicore *pc)
427 : : {
428 : : u16 tmp = pcicore_read16(pc, SSB_PCICORE_SPROM(0));
429 : : if (((tmp & 0xF000) >> 12) != pc->dev->core_index) {
430 : : tmp &= ~0xF000;
431 : : tmp |= (pc->dev->core_index << 12);
432 : : pcicore_write16(pc, SSB_PCICORE_SPROM(0), tmp);
433 : : }
434 : : }
435 : :
436 : 0 : static u8 ssb_pcicore_polarity_workaround(struct ssb_pcicore *pc)
437 : : {
438 [ # # ]: 0 : return (ssb_pcie_read(pc, 0x204) & 0x10) ? 0xC0 : 0x80;
439 : : }
440 : :
441 : 0 : static void ssb_pcicore_serdes_workaround(struct ssb_pcicore *pc)
442 : : {
443 : 0 : const u8 serdes_pll_device = 0x1D;
444 : 0 : const u8 serdes_rx_device = 0x1F;
445 : 0 : u16 tmp;
446 : :
447 : 0 : ssb_pcie_mdio_write(pc, serdes_rx_device, 1 /* Control */,
448 : 0 : ssb_pcicore_polarity_workaround(pc));
449 : 0 : tmp = ssb_pcie_mdio_read(pc, serdes_pll_device, 1 /* Control */);
450 [ # # ]: 0 : if (tmp & 0x4000)
451 : 0 : ssb_pcie_mdio_write(pc, serdes_pll_device, 1, tmp & ~0x4000);
452 : 0 : }
453 : :
454 : : static void ssb_pcicore_pci_setup_workarounds(struct ssb_pcicore *pc)
455 : : {
456 : : struct ssb_device *pdev = pc->dev;
457 : : struct ssb_bus *bus = pdev->bus;
458 : : u32 tmp;
459 : :
460 : : tmp = pcicore_read32(pc, SSB_PCICORE_SBTOPCI2);
461 : : tmp |= SSB_PCICORE_SBTOPCI_PREF;
462 : : tmp |= SSB_PCICORE_SBTOPCI_BURST;
463 : : pcicore_write32(pc, SSB_PCICORE_SBTOPCI2, tmp);
464 : :
465 : : if (pdev->id.revision < 5) {
466 : : tmp = ssb_read32(pdev, SSB_IMCFGLO);
467 : : tmp &= ~SSB_IMCFGLO_SERTO;
468 : : tmp |= 2;
469 : : tmp &= ~SSB_IMCFGLO_REQTO;
470 : : tmp |= 3 << SSB_IMCFGLO_REQTO_SHIFT;
471 : : ssb_write32(pdev, SSB_IMCFGLO, tmp);
472 : : ssb_commit_settings(bus);
473 : : } else if (pdev->id.revision >= 11) {
474 : : tmp = pcicore_read32(pc, SSB_PCICORE_SBTOPCI2);
475 : : tmp |= SSB_PCICORE_SBTOPCI_MRM;
476 : : pcicore_write32(pc, SSB_PCICORE_SBTOPCI2, tmp);
477 : : }
478 : : }
479 : :
480 : 0 : static void ssb_pcicore_pcie_setup_workarounds(struct ssb_pcicore *pc)
481 : : {
482 : 0 : u32 tmp;
483 : 0 : u8 rev = pc->dev->id.revision;
484 : :
485 [ # # ]: 0 : if (rev == 0 || rev == 1) {
486 : : /* TLP Workaround register. */
487 : 0 : tmp = ssb_pcie_read(pc, 0x4);
488 : 0 : tmp |= 0x8;
489 : 0 : ssb_pcie_write(pc, 0x4, tmp);
490 : : }
491 [ # # ]: 0 : if (rev == 1) {
492 : : /* DLLP Link Control register. */
493 : 0 : tmp = ssb_pcie_read(pc, 0x100);
494 : 0 : tmp |= 0x40;
495 : 0 : ssb_pcie_write(pc, 0x100, tmp);
496 : : }
497 : :
498 [ # # ]: 0 : if (rev == 0) {
499 : 0 : const u8 serdes_rx_device = 0x1F;
500 : :
501 : 0 : ssb_pcie_mdio_write(pc, serdes_rx_device,
502 : : 2 /* Timer */, 0x8128);
503 : 0 : ssb_pcie_mdio_write(pc, serdes_rx_device,
504 : : 6 /* CDR */, 0x0100);
505 : 0 : ssb_pcie_mdio_write(pc, serdes_rx_device,
506 : : 7 /* CDR BW */, 0x1466);
507 [ # # ]: 0 : } else if (rev == 3 || rev == 4 || rev == 5) {
508 : : /* TODO: DLLP Power Management Threshold */
509 : 0 : ssb_pcicore_serdes_workaround(pc);
510 : : /* TODO: ASPM */
511 : : } else if (rev == 7) {
512 : : /* TODO: No PLL down */
513 : 0 : }
514 : :
515 [ # # ]: 0 : if (rev >= 6) {
516 : : /* Miscellaneous Configuration Fixup */
517 : 0 : tmp = pcicore_read16(pc, SSB_PCICORE_SPROM(5));
518 [ # # ]: 0 : if (!(tmp & 0x8000))
519 : 0 : pcicore_write16(pc, SSB_PCICORE_SPROM(5),
520 : 0 : tmp | 0x8000);
521 : : }
522 : 0 : }
523 : :
524 : : /**************************************************
525 : : * Generic and Clientmode operation code.
526 : : **************************************************/
527 : :
528 : 0 : static void ssb_pcicore_init_clientmode(struct ssb_pcicore *pc)
529 : : {
530 : 0 : struct ssb_device *pdev = pc->dev;
531 : 0 : struct ssb_bus *bus = pdev->bus;
532 : :
533 [ # # ]: 0 : if (bus->bustype == SSB_BUSTYPE_PCI)
534 : 0 : ssb_pcicore_fix_sprom_core_index(pc);
535 : :
536 : : /* Disable PCI interrupts. */
537 : 0 : ssb_write32(pdev, SSB_INTVEC, 0);
538 : :
539 : : /* Additional PCIe always once-executed workarounds */
540 [ # # ]: 0 : if (pc->dev->id.coreid == SSB_DEV_PCIE) {
541 : 0 : ssb_pcicore_serdes_workaround(pc);
542 : : /* TODO: ASPM */
543 : : /* TODO: Clock Request Update */
544 : : }
545 : 0 : }
546 : :
547 : 0 : void ssb_pcicore_init(struct ssb_pcicore *pc)
548 : : {
549 : 0 : struct ssb_device *dev = pc->dev;
550 : :
551 [ # # ]: 0 : if (!dev)
552 : : return;
553 [ # # ]: 0 : if (!ssb_device_is_enabled(dev))
554 : 0 : ssb_device_enable(dev, 0);
555 : :
556 : : #ifdef CONFIG_SSB_PCICORE_HOSTMODE
557 : : pc->hostmode = pcicore_is_in_hostmode(pc);
558 : : if (pc->hostmode)
559 : : ssb_pcicore_init_hostmode(pc);
560 : : #endif /* CONFIG_SSB_PCICORE_HOSTMODE */
561 [ # # ]: 0 : if (!pc->hostmode)
562 : 0 : ssb_pcicore_init_clientmode(pc);
563 : : }
564 : :
565 : 0 : static u32 ssb_pcie_read(struct ssb_pcicore *pc, u32 address)
566 : : {
567 : 0 : pcicore_write32(pc, 0x130, address);
568 : 0 : return pcicore_read32(pc, 0x134);
569 : : }
570 : :
571 : 0 : static void ssb_pcie_write(struct ssb_pcicore *pc, u32 address, u32 data)
572 : : {
573 : 0 : pcicore_write32(pc, 0x130, address);
574 : 0 : pcicore_write32(pc, 0x134, data);
575 : 0 : }
576 : :
577 : 0 : static void ssb_pcie_mdio_set_phy(struct ssb_pcicore *pc, u8 phy)
578 : : {
579 : 0 : const u16 mdio_control = 0x128;
580 : 0 : const u16 mdio_data = 0x12C;
581 : 0 : u32 v;
582 : 0 : int i;
583 : :
584 : 0 : v = (1 << 30); /* Start of Transaction */
585 : 0 : v |= (1 << 28); /* Write Transaction */
586 : 0 : v |= (1 << 17); /* Turnaround */
587 : 0 : v |= (0x1F << 18);
588 : 0 : v |= (phy << 4);
589 : 0 : pcicore_write32(pc, mdio_data, v);
590 : :
591 : 0 : udelay(10);
592 [ # # ]: 0 : for (i = 0; i < 200; i++) {
593 : 0 : v = pcicore_read32(pc, mdio_control);
594 [ # # ]: 0 : if (v & 0x100 /* Trans complete */)
595 : : break;
596 : 0 : msleep(1);
597 : : }
598 : 0 : }
599 : :
600 : 0 : static u16 ssb_pcie_mdio_read(struct ssb_pcicore *pc, u8 device, u8 address)
601 : : {
602 : 0 : const u16 mdio_control = 0x128;
603 : 0 : const u16 mdio_data = 0x12C;
604 : 0 : int max_retries = 10;
605 : 0 : u16 ret = 0;
606 : 0 : u32 v;
607 : 0 : int i;
608 : :
609 : 0 : v = 0x80; /* Enable Preamble Sequence */
610 : 0 : v |= 0x2; /* MDIO Clock Divisor */
611 : 0 : pcicore_write32(pc, mdio_control, v);
612 : :
613 [ # # ]: 0 : if (pc->dev->id.revision >= 10) {
614 : 0 : max_retries = 200;
615 : 0 : ssb_pcie_mdio_set_phy(pc, device);
616 : : }
617 : :
618 : 0 : v = (1 << 30); /* Start of Transaction */
619 : 0 : v |= (1 << 29); /* Read Transaction */
620 : 0 : v |= (1 << 17); /* Turnaround */
621 [ # # ]: 0 : if (pc->dev->id.revision < 10)
622 : 0 : v |= (u32)device << 22;
623 : 0 : v |= (u32)address << 18;
624 : 0 : pcicore_write32(pc, mdio_data, v);
625 : : /* Wait for the device to complete the transaction */
626 : 0 : udelay(10);
627 [ # # ]: 0 : for (i = 0; i < max_retries; i++) {
628 : 0 : v = pcicore_read32(pc, mdio_control);
629 [ # # ]: 0 : if (v & 0x100 /* Trans complete */) {
630 : 0 : udelay(10);
631 : 0 : ret = pcicore_read32(pc, mdio_data);
632 : 0 : break;
633 : : }
634 : 0 : msleep(1);
635 : : }
636 : 0 : pcicore_write32(pc, mdio_control, 0);
637 : 0 : return ret;
638 : : }
639 : :
640 : 0 : static void ssb_pcie_mdio_write(struct ssb_pcicore *pc, u8 device,
641 : : u8 address, u16 data)
642 : : {
643 : 0 : const u16 mdio_control = 0x128;
644 : 0 : const u16 mdio_data = 0x12C;
645 : 0 : int max_retries = 10;
646 : 0 : u32 v;
647 : 0 : int i;
648 : :
649 : 0 : v = 0x80; /* Enable Preamble Sequence */
650 : 0 : v |= 0x2; /* MDIO Clock Divisor */
651 : 0 : pcicore_write32(pc, mdio_control, v);
652 : :
653 [ # # ]: 0 : if (pc->dev->id.revision >= 10) {
654 : 0 : max_retries = 200;
655 : 0 : ssb_pcie_mdio_set_phy(pc, device);
656 : : }
657 : :
658 : 0 : v = (1 << 30); /* Start of Transaction */
659 : 0 : v |= (1 << 28); /* Write Transaction */
660 : 0 : v |= (1 << 17); /* Turnaround */
661 [ # # ]: 0 : if (pc->dev->id.revision < 10)
662 : 0 : v |= (u32)device << 22;
663 : 0 : v |= (u32)address << 18;
664 : 0 : v |= data;
665 : 0 : pcicore_write32(pc, mdio_data, v);
666 : : /* Wait for the device to complete the transaction */
667 : 0 : udelay(10);
668 [ # # ]: 0 : for (i = 0; i < max_retries; i++) {
669 : 0 : v = pcicore_read32(pc, mdio_control);
670 [ # # ]: 0 : if (v & 0x100 /* Trans complete */)
671 : : break;
672 : 0 : msleep(1);
673 : : }
674 : 0 : pcicore_write32(pc, mdio_control, 0);
675 : 0 : }
676 : :
677 : 0 : int ssb_pcicore_dev_irqvecs_enable(struct ssb_pcicore *pc,
678 : : struct ssb_device *dev)
679 : : {
680 : 0 : struct ssb_device *pdev = pc->dev;
681 : 0 : struct ssb_bus *bus;
682 : 0 : int err = 0;
683 : 0 : u32 tmp;
684 : :
685 [ # # ]: 0 : if (dev->bus->bustype != SSB_BUSTYPE_PCI) {
686 : : /* This SSB device is not on a PCI host-bus. So the IRQs are
687 : : * not routed through the PCI core.
688 : : * So we must not enable routing through the PCI core. */
689 : 0 : goto out;
690 : : }
691 : :
692 [ # # ]: 0 : if (!pdev)
693 : 0 : goto out;
694 : 0 : bus = pdev->bus;
695 : :
696 [ # # ]: 0 : might_sleep_if(pdev->id.coreid != SSB_DEV_PCI);
697 : :
698 : : /* Enable interrupts for this device. */
699 [ # # # # ]: 0 : if ((pdev->id.revision >= 6) || (pdev->id.coreid == SSB_DEV_PCIE)) {
700 : 0 : u32 coremask;
701 : :
702 : : /* Calculate the "coremask" for the device. */
703 : 0 : coremask = (1 << dev->core_index);
704 : :
705 [ # # ]: 0 : WARN_ON(bus->bustype != SSB_BUSTYPE_PCI);
706 : 0 : err = pci_read_config_dword(bus->host_pci, SSB_PCI_IRQMASK, &tmp);
707 [ # # ]: 0 : if (err)
708 : 0 : goto out;
709 : 0 : tmp |= coremask << 8;
710 : 0 : err = pci_write_config_dword(bus->host_pci, SSB_PCI_IRQMASK, tmp);
711 [ # # ]: 0 : if (err)
712 : 0 : goto out;
713 : : } else {
714 : 0 : u32 intvec;
715 : :
716 : 0 : intvec = ssb_read32(pdev, SSB_INTVEC);
717 : 0 : tmp = ssb_read32(dev, SSB_TPSFLAG);
718 : 0 : tmp &= SSB_TPSFLAG_BPFLAG;
719 : 0 : intvec |= (1 << tmp);
720 : 0 : ssb_write32(pdev, SSB_INTVEC, intvec);
721 : : }
722 : :
723 : : /* Setup PCIcore operation. */
724 [ # # ]: 0 : if (pc->setup_done)
725 : 0 : goto out;
726 [ # # ]: 0 : if (pdev->id.coreid == SSB_DEV_PCI) {
727 : 0 : ssb_pcicore_pci_setup_workarounds(pc);
728 : : } else {
729 [ # # ]: 0 : WARN_ON(pdev->id.coreid != SSB_DEV_PCIE);
730 : 0 : ssb_pcicore_pcie_setup_workarounds(pc);
731 : : }
732 : 0 : pc->setup_done = 1;
733 : 0 : out:
734 : 0 : return err;
735 : : }
736 : : EXPORT_SYMBOL(ssb_pcicore_dev_irqvecs_enable);
|