diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2008-02-24 00:05:06 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2008-02-24 00:07:10 -0500 |
commit | bdc08942897f6be33d00bb659761516f4652836d (patch) | |
tree | 238ec76128b8feb9da7e3ad8b85a3b15a318dd3f /drivers/ssb | |
parent | 85b80ebfa4384b8ea30cc1af9617db30319a9ccd (diff) | |
parent | 1b04ab4597725f75f94942da9aa40daa7b9a4bd9 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: (37 commits)
[NETFILTER]: fix ebtable targets return
[IP_TUNNEL]: Don't limit the number of tunnels with generic name explicitly.
[NET]: Restore sanity wrt. print_mac().
[NEIGH]: Fix race between neighbor lookup and table's hash_rnd update.
[RTNL]: Validate hardware and broadcast address attribute for RTM_NEWLINK
tg3: ethtool phys_id default
[BNX2]: Update version to 1.7.4.
[BNX2]: Disable parallel detect on an HP blade.
[BNX2]: More 5706S link down workaround.
ssb: Fix support for PCI devices behind a SSB->PCI bridge
zd1211rw: fix sparse warnings
rtl818x: fix sparse warnings
ssb: Fix pcicore cardbus mode
ssb: Make the GPIO API reentrancy safe
ssb: Fix the GPIO API
ssb: Fix watchdog access for devices without a chipcommon
ssb: Fix serial console on new bcm47xx devices
ath5k: Fix build warnings on some 64-bit platforms.
WDEV, ath5k, don't return int from bool function
WDEV: ath5k, fix lock imbalance
...
Diffstat (limited to 'drivers/ssb')
-rw-r--r-- | drivers/ssb/Kconfig | 6 | ||||
-rw-r--r-- | drivers/ssb/Makefile | 1 | ||||
-rw-r--r-- | drivers/ssb/driver_chipcommon.c | 65 | ||||
-rw-r--r-- | drivers/ssb/driver_extif.c | 25 | ||||
-rw-r--r-- | drivers/ssb/driver_pcicore.c | 45 | ||||
-rw-r--r-- | drivers/ssb/embedded.c | 132 | ||||
-rw-r--r-- | drivers/ssb/main.c | 4 |
7 files changed, 256 insertions, 22 deletions
diff --git a/drivers/ssb/Kconfig b/drivers/ssb/Kconfig index d976660cb7f0..78fd33125e02 100644 --- a/drivers/ssb/Kconfig +++ b/drivers/ssb/Kconfig | |||
@@ -105,6 +105,12 @@ config SSB_DRIVER_MIPS | |||
105 | 105 | ||
106 | If unsure, say N | 106 | If unsure, say N |
107 | 107 | ||
108 | # Assumption: We are on embedded, if we compile the MIPS core. | ||
109 | config SSB_EMBEDDED | ||
110 | bool | ||
111 | depends on SSB_DRIVER_MIPS | ||
112 | default y | ||
113 | |||
108 | config SSB_DRIVER_EXTIF | 114 | config SSB_DRIVER_EXTIF |
109 | bool "SSB Broadcom EXTIF core driver (EXPERIMENTAL)" | 115 | bool "SSB Broadcom EXTIF core driver (EXPERIMENTAL)" |
110 | depends on SSB_DRIVER_MIPS && EXPERIMENTAL | 116 | depends on SSB_DRIVER_MIPS && EXPERIMENTAL |
diff --git a/drivers/ssb/Makefile b/drivers/ssb/Makefile index 7be397595805..e235144add7c 100644 --- a/drivers/ssb/Makefile +++ b/drivers/ssb/Makefile | |||
@@ -1,5 +1,6 @@ | |||
1 | # core | 1 | # core |
2 | ssb-y += main.o scan.o | 2 | ssb-y += main.o scan.o |
3 | ssb-$(CONFIG_SSB_EMBEDDED) += embedded.o | ||
3 | 4 | ||
4 | # host support | 5 | # host support |
5 | ssb-$(CONFIG_SSB_PCIHOST) += pci.o pcihost_wrapper.o | 6 | ssb-$(CONFIG_SSB_PCIHOST) += pci.o pcihost_wrapper.o |
diff --git a/drivers/ssb/driver_chipcommon.c b/drivers/ssb/driver_chipcommon.c index 6fbf1c53b6f2..e586321a473a 100644 --- a/drivers/ssb/driver_chipcommon.c +++ b/drivers/ssb/driver_chipcommon.c | |||
@@ -39,12 +39,14 @@ static inline void chipco_write32(struct ssb_chipcommon *cc, | |||
39 | ssb_write32(cc->dev, offset, value); | 39 | ssb_write32(cc->dev, offset, value); |
40 | } | 40 | } |
41 | 41 | ||
42 | static inline void chipco_write32_masked(struct ssb_chipcommon *cc, u16 offset, | 42 | static inline u32 chipco_write32_masked(struct ssb_chipcommon *cc, u16 offset, |
43 | u32 mask, u32 value) | 43 | u32 mask, u32 value) |
44 | { | 44 | { |
45 | value &= mask; | 45 | value &= mask; |
46 | value |= chipco_read32(cc, offset) & ~mask; | 46 | value |= chipco_read32(cc, offset) & ~mask; |
47 | chipco_write32(cc, offset, value); | 47 | chipco_write32(cc, offset, value); |
48 | |||
49 | return value; | ||
48 | } | 50 | } |
49 | 51 | ||
50 | void ssb_chipco_set_clockmode(struct ssb_chipcommon *cc, | 52 | void ssb_chipco_set_clockmode(struct ssb_chipcommon *cc, |
@@ -356,14 +358,29 @@ u32 ssb_chipco_gpio_in(struct ssb_chipcommon *cc, u32 mask) | |||
356 | return chipco_read32(cc, SSB_CHIPCO_GPIOIN) & mask; | 358 | return chipco_read32(cc, SSB_CHIPCO_GPIOIN) & mask; |
357 | } | 359 | } |
358 | 360 | ||
359 | void ssb_chipco_gpio_out(struct ssb_chipcommon *cc, u32 mask, u32 value) | 361 | u32 ssb_chipco_gpio_out(struct ssb_chipcommon *cc, u32 mask, u32 value) |
362 | { | ||
363 | return chipco_write32_masked(cc, SSB_CHIPCO_GPIOOUT, mask, value); | ||
364 | } | ||
365 | |||
366 | u32 ssb_chipco_gpio_outen(struct ssb_chipcommon *cc, u32 mask, u32 value) | ||
367 | { | ||
368 | return chipco_write32_masked(cc, SSB_CHIPCO_GPIOOUTEN, mask, value); | ||
369 | } | ||
370 | |||
371 | u32 ssb_chipco_gpio_control(struct ssb_chipcommon *cc, u32 mask, u32 value) | ||
372 | { | ||
373 | return chipco_write32_masked(cc, SSB_CHIPCO_GPIOCTL, mask, value); | ||
374 | } | ||
375 | |||
376 | u32 ssb_chipco_gpio_intmask(struct ssb_chipcommon *cc, u32 mask, u32 value) | ||
360 | { | 377 | { |
361 | chipco_write32_masked(cc, SSB_CHIPCO_GPIOOUT, mask, value); | 378 | return chipco_write32_masked(cc, SSB_CHIPCO_GPIOIRQ, mask, value); |
362 | } | 379 | } |
363 | 380 | ||
364 | void ssb_chipco_gpio_outen(struct ssb_chipcommon *cc, u32 mask, u32 value) | 381 | u32 ssb_chipco_gpio_polarity(struct ssb_chipcommon *cc, u32 mask, u32 value) |
365 | { | 382 | { |
366 | chipco_write32_masked(cc, SSB_CHIPCO_GPIOOUTEN, mask, value); | 383 | return chipco_write32_masked(cc, SSB_CHIPCO_GPIOPOL, mask, value); |
367 | } | 384 | } |
368 | 385 | ||
369 | #ifdef CONFIG_SSB_SERIAL | 386 | #ifdef CONFIG_SSB_SERIAL |
@@ -376,6 +393,7 @@ int ssb_chipco_serial_init(struct ssb_chipcommon *cc, | |||
376 | unsigned int irq; | 393 | unsigned int irq; |
377 | u32 baud_base, div; | 394 | u32 baud_base, div; |
378 | u32 i, n; | 395 | u32 i, n; |
396 | unsigned int ccrev = cc->dev->id.revision; | ||
379 | 397 | ||
380 | plltype = (cc->capabilities & SSB_CHIPCO_CAP_PLLT); | 398 | plltype = (cc->capabilities & SSB_CHIPCO_CAP_PLLT); |
381 | irq = ssb_mips_irq(cc->dev); | 399 | irq = ssb_mips_irq(cc->dev); |
@@ -387,14 +405,39 @@ int ssb_chipco_serial_init(struct ssb_chipcommon *cc, | |||
387 | chipco_read32(cc, SSB_CHIPCO_CLOCK_M2)); | 405 | chipco_read32(cc, SSB_CHIPCO_CLOCK_M2)); |
388 | div = 1; | 406 | div = 1; |
389 | } else { | 407 | } else { |
390 | if (cc->dev->id.revision >= 11) { | 408 | if (ccrev == 20) { |
409 | /* BCM5354 uses constant 25MHz clock */ | ||
410 | baud_base = 25000000; | ||
411 | div = 48; | ||
412 | /* Set the override bit so we don't divide it */ | ||
413 | chipco_write32(cc, SSB_CHIPCO_CORECTL, | ||
414 | chipco_read32(cc, SSB_CHIPCO_CORECTL) | ||
415 | | SSB_CHIPCO_CORECTL_UARTCLK0); | ||
416 | } else if ((ccrev >= 11) && (ccrev != 15)) { | ||
391 | /* Fixed ALP clock */ | 417 | /* Fixed ALP clock */ |
392 | baud_base = 20000000; | 418 | baud_base = 20000000; |
419 | if (cc->capabilities & SSB_CHIPCO_CAP_PMU) { | ||
420 | /* FIXME: baud_base is different for devices with a PMU */ | ||
421 | SSB_WARN_ON(1); | ||
422 | } | ||
393 | div = 1; | 423 | div = 1; |
424 | if (ccrev >= 21) { | ||
425 | /* Turn off UART clock before switching clocksource. */ | ||
426 | chipco_write32(cc, SSB_CHIPCO_CORECTL, | ||
427 | chipco_read32(cc, SSB_CHIPCO_CORECTL) | ||
428 | & ~SSB_CHIPCO_CORECTL_UARTCLKEN); | ||
429 | } | ||
394 | /* Set the override bit so we don't divide it */ | 430 | /* Set the override bit so we don't divide it */ |
395 | chipco_write32(cc, SSB_CHIPCO_CORECTL, | 431 | chipco_write32(cc, SSB_CHIPCO_CORECTL, |
396 | SSB_CHIPCO_CORECTL_UARTCLK0); | 432 | chipco_read32(cc, SSB_CHIPCO_CORECTL) |
397 | } else if (cc->dev->id.revision >= 3) { | 433 | | SSB_CHIPCO_CORECTL_UARTCLK0); |
434 | if (ccrev >= 21) { | ||
435 | /* Re-enable the UART clock. */ | ||
436 | chipco_write32(cc, SSB_CHIPCO_CORECTL, | ||
437 | chipco_read32(cc, SSB_CHIPCO_CORECTL) | ||
438 | | SSB_CHIPCO_CORECTL_UARTCLKEN); | ||
439 | } | ||
440 | } else if (ccrev >= 3) { | ||
398 | /* Internal backplane clock */ | 441 | /* Internal backplane clock */ |
399 | baud_base = ssb_clockspeed(bus); | 442 | baud_base = ssb_clockspeed(bus); |
400 | div = chipco_read32(cc, SSB_CHIPCO_CLKDIV) | 443 | div = chipco_read32(cc, SSB_CHIPCO_CLKDIV) |
@@ -406,7 +449,7 @@ int ssb_chipco_serial_init(struct ssb_chipcommon *cc, | |||
406 | } | 449 | } |
407 | 450 | ||
408 | /* Clock source depends on strapping if UartClkOverride is unset */ | 451 | /* Clock source depends on strapping if UartClkOverride is unset */ |
409 | if ((cc->dev->id.revision > 0) && | 452 | if ((ccrev > 0) && |
410 | !(chipco_read32(cc, SSB_CHIPCO_CORECTL) & SSB_CHIPCO_CORECTL_UARTCLK0)) { | 453 | !(chipco_read32(cc, SSB_CHIPCO_CORECTL) & SSB_CHIPCO_CORECTL_UARTCLK0)) { |
411 | if ((cc->capabilities & SSB_CHIPCO_CAP_UARTCLK) == | 454 | if ((cc->capabilities & SSB_CHIPCO_CAP_UARTCLK) == |
412 | SSB_CHIPCO_CAP_UARTCLK_INT) { | 455 | SSB_CHIPCO_CAP_UARTCLK_INT) { |
@@ -428,7 +471,7 @@ int ssb_chipco_serial_init(struct ssb_chipcommon *cc, | |||
428 | cc_mmio = cc->dev->bus->mmio + (cc->dev->core_index * SSB_CORE_SIZE); | 471 | cc_mmio = cc->dev->bus->mmio + (cc->dev->core_index * SSB_CORE_SIZE); |
429 | uart_regs = cc_mmio + SSB_CHIPCO_UART0_DATA; | 472 | uart_regs = cc_mmio + SSB_CHIPCO_UART0_DATA; |
430 | /* Offset changed at after rev 0 */ | 473 | /* Offset changed at after rev 0 */ |
431 | if (cc->dev->id.revision == 0) | 474 | if (ccrev == 0) |
432 | uart_regs += (i * 8); | 475 | uart_regs += (i * 8); |
433 | else | 476 | else |
434 | uart_regs += (i * 256); | 477 | uart_regs += (i * 256); |
diff --git a/drivers/ssb/driver_extif.c b/drivers/ssb/driver_extif.c index fe55eb8b038a..c3e1d3e6d610 100644 --- a/drivers/ssb/driver_extif.c +++ b/drivers/ssb/driver_extif.c | |||
@@ -27,12 +27,14 @@ static inline void extif_write32(struct ssb_extif *extif, u16 offset, u32 value) | |||
27 | ssb_write32(extif->dev, offset, value); | 27 | ssb_write32(extif->dev, offset, value); |
28 | } | 28 | } |
29 | 29 | ||
30 | static inline void extif_write32_masked(struct ssb_extif *extif, u16 offset, | 30 | static inline u32 extif_write32_masked(struct ssb_extif *extif, u16 offset, |
31 | u32 mask, u32 value) | 31 | u32 mask, u32 value) |
32 | { | 32 | { |
33 | value &= mask; | 33 | value &= mask; |
34 | value |= extif_read32(extif, offset) & ~mask; | 34 | value |= extif_read32(extif, offset) & ~mask; |
35 | extif_write32(extif, offset, value); | 35 | extif_write32(extif, offset, value); |
36 | |||
37 | return value; | ||
36 | } | 38 | } |
37 | 39 | ||
38 | #ifdef CONFIG_SSB_SERIAL | 40 | #ifdef CONFIG_SSB_SERIAL |
@@ -110,20 +112,35 @@ void ssb_extif_get_clockcontrol(struct ssb_extif *extif, | |||
110 | *m = extif_read32(extif, SSB_EXTIF_CLOCK_SB); | 112 | *m = extif_read32(extif, SSB_EXTIF_CLOCK_SB); |
111 | } | 113 | } |
112 | 114 | ||
115 | void ssb_extif_watchdog_timer_set(struct ssb_extif *extif, | ||
116 | u32 ticks) | ||
117 | { | ||
118 | extif_write32(extif, SSB_EXTIF_WATCHDOG, ticks); | ||
119 | } | ||
120 | |||
113 | u32 ssb_extif_gpio_in(struct ssb_extif *extif, u32 mask) | 121 | u32 ssb_extif_gpio_in(struct ssb_extif *extif, u32 mask) |
114 | { | 122 | { |
115 | return extif_read32(extif, SSB_EXTIF_GPIO_IN) & mask; | 123 | return extif_read32(extif, SSB_EXTIF_GPIO_IN) & mask; |
116 | } | 124 | } |
117 | 125 | ||
118 | void ssb_extif_gpio_out(struct ssb_extif *extif, u32 mask, u32 value) | 126 | u32 ssb_extif_gpio_out(struct ssb_extif *extif, u32 mask, u32 value) |
119 | { | 127 | { |
120 | return extif_write32_masked(extif, SSB_EXTIF_GPIO_OUT(0), | 128 | return extif_write32_masked(extif, SSB_EXTIF_GPIO_OUT(0), |
121 | mask, value); | 129 | mask, value); |
122 | } | 130 | } |
123 | 131 | ||
124 | void ssb_extif_gpio_outen(struct ssb_extif *extif, u32 mask, u32 value) | 132 | u32 ssb_extif_gpio_outen(struct ssb_extif *extif, u32 mask, u32 value) |
125 | { | 133 | { |
126 | return extif_write32_masked(extif, SSB_EXTIF_GPIO_OUTEN(0), | 134 | return extif_write32_masked(extif, SSB_EXTIF_GPIO_OUTEN(0), |
127 | mask, value); | 135 | mask, value); |
128 | } | 136 | } |
129 | 137 | ||
138 | u32 ssb_extif_gpio_polarity(struct ssb_extif *extif, u32 mask, u32 value) | ||
139 | { | ||
140 | return extif_write32_masked(extif, SSB_EXTIF_GPIO_INTPOL, mask, value); | ||
141 | } | ||
142 | |||
143 | u32 ssb_extif_gpio_intmask(struct ssb_extif *extif, u32 mask, u32 value) | ||
144 | { | ||
145 | return extif_write32_masked(extif, SSB_EXTIF_GPIO_INTMASK, mask, value); | ||
146 | } | ||
diff --git a/drivers/ssb/driver_pcicore.c b/drivers/ssb/driver_pcicore.c index 2faaa906d5d6..6d99a9880055 100644 --- a/drivers/ssb/driver_pcicore.c +++ b/drivers/ssb/driver_pcicore.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/ssb/ssb.h> | 11 | #include <linux/ssb/ssb.h> |
12 | #include <linux/pci.h> | 12 | #include <linux/pci.h> |
13 | #include <linux/delay.h> | 13 | #include <linux/delay.h> |
14 | #include <linux/ssb/ssb_embedded.h> | ||
14 | 15 | ||
15 | #include "ssb_private.h" | 16 | #include "ssb_private.h" |
16 | 17 | ||
@@ -27,6 +28,18 @@ void pcicore_write32(struct ssb_pcicore *pc, u16 offset, u32 value) | |||
27 | ssb_write32(pc->dev, offset, value); | 28 | ssb_write32(pc->dev, offset, value); |
28 | } | 29 | } |
29 | 30 | ||
31 | static inline | ||
32 | u16 pcicore_read16(struct ssb_pcicore *pc, u16 offset) | ||
33 | { | ||
34 | return ssb_read16(pc->dev, offset); | ||
35 | } | ||
36 | |||
37 | static inline | ||
38 | void pcicore_write16(struct ssb_pcicore *pc, u16 offset, u16 value) | ||
39 | { | ||
40 | ssb_write16(pc->dev, offset, value); | ||
41 | } | ||
42 | |||
30 | /************************************************** | 43 | /************************************************** |
31 | * Code for hostmode operation. | 44 | * Code for hostmode operation. |
32 | **************************************************/ | 45 | **************************************************/ |
@@ -66,6 +79,7 @@ int pcibios_plat_dev_init(struct pci_dev *d) | |||
66 | base = &ssb_pcicore_pcibus_iobase; | 79 | base = &ssb_pcicore_pcibus_iobase; |
67 | else | 80 | else |
68 | base = &ssb_pcicore_pcibus_membase; | 81 | base = &ssb_pcicore_pcibus_membase; |
82 | res->flags |= IORESOURCE_PCI_FIXED; | ||
69 | if (res->end) { | 83 | if (res->end) { |
70 | size = res->end - res->start + 1; | 84 | size = res->end - res->start + 1; |
71 | if (*base & (size - 1)) | 85 | if (*base & (size - 1)) |
@@ -88,10 +102,12 @@ int pcibios_plat_dev_init(struct pci_dev *d) | |||
88 | 102 | ||
89 | static void __init ssb_fixup_pcibridge(struct pci_dev *dev) | 103 | static void __init ssb_fixup_pcibridge(struct pci_dev *dev) |
90 | { | 104 | { |
105 | u8 lat; | ||
106 | |||
91 | if (dev->bus->number != 0 || PCI_SLOT(dev->devfn) != 0) | 107 | if (dev->bus->number != 0 || PCI_SLOT(dev->devfn) != 0) |
92 | return; | 108 | return; |
93 | 109 | ||
94 | ssb_printk(KERN_INFO "PCI: fixing up bridge\n"); | 110 | ssb_printk(KERN_INFO "PCI: Fixing up bridge %s\n", pci_name(dev)); |
95 | 111 | ||
96 | /* Enable PCI bridge bus mastering and memory space */ | 112 | /* Enable PCI bridge bus mastering and memory space */ |
97 | pci_set_master(dev); | 113 | pci_set_master(dev); |
@@ -101,7 +117,10 @@ static void __init ssb_fixup_pcibridge(struct pci_dev *dev) | |||
101 | pci_write_config_dword(dev, SSB_BAR1_CONTROL, 3); | 117 | pci_write_config_dword(dev, SSB_BAR1_CONTROL, 3); |
102 | 118 | ||
103 | /* Make sure our latency is high enough to handle the devices behind us */ | 119 | /* Make sure our latency is high enough to handle the devices behind us */ |
104 | pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0xa8); | 120 | lat = 168; |
121 | ssb_printk(KERN_INFO "PCI: Fixing latency timer of device %s to %u\n", | ||
122 | pci_name(dev), lat); | ||
123 | pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat); | ||
105 | } | 124 | } |
106 | DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, ssb_fixup_pcibridge); | 125 | DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, ssb_fixup_pcibridge); |
107 | 126 | ||
@@ -117,8 +136,10 @@ static u32 get_cfgspace_addr(struct ssb_pcicore *pc, | |||
117 | u32 addr = 0; | 136 | u32 addr = 0; |
118 | u32 tmp; | 137 | u32 tmp; |
119 | 138 | ||
120 | if (unlikely(pc->cardbusmode && dev > 1)) | 139 | /* We do only have one cardbus device behind the bridge. */ |
140 | if (pc->cardbusmode && (dev >= 1)) | ||
121 | goto out; | 141 | goto out; |
142 | |||
122 | if (bus == 0) { | 143 | if (bus == 0) { |
123 | /* Type 0 transaction */ | 144 | /* Type 0 transaction */ |
124 | if (unlikely(dev >= SSB_PCI_SLOT_MAX)) | 145 | if (unlikely(dev >= SSB_PCI_SLOT_MAX)) |
@@ -279,14 +300,14 @@ static struct resource ssb_pcicore_mem_resource = { | |||
279 | .name = "SSB PCIcore external memory", | 300 | .name = "SSB PCIcore external memory", |
280 | .start = SSB_PCI_DMA, | 301 | .start = SSB_PCI_DMA, |
281 | .end = SSB_PCI_DMA + SSB_PCI_DMA_SZ - 1, | 302 | .end = SSB_PCI_DMA + SSB_PCI_DMA_SZ - 1, |
282 | .flags = IORESOURCE_MEM, | 303 | .flags = IORESOURCE_MEM | IORESOURCE_PCI_FIXED, |
283 | }; | 304 | }; |
284 | 305 | ||
285 | static struct resource ssb_pcicore_io_resource = { | 306 | static struct resource ssb_pcicore_io_resource = { |
286 | .name = "SSB PCIcore external I/O", | 307 | .name = "SSB PCIcore external I/O", |
287 | .start = 0x100, | 308 | .start = 0x100, |
288 | .end = 0x7FF, | 309 | .end = 0x7FF, |
289 | .flags = IORESOURCE_IO, | 310 | .flags = IORESOURCE_IO | IORESOURCE_PCI_FIXED, |
290 | }; | 311 | }; |
291 | 312 | ||
292 | static struct pci_controller ssb_pcicore_controller = { | 313 | static struct pci_controller ssb_pcicore_controller = { |
@@ -318,7 +339,16 @@ static void ssb_pcicore_init_hostmode(struct ssb_pcicore *pc) | |||
318 | pcicore_write32(pc, SSB_PCICORE_ARBCTL, val); | 339 | pcicore_write32(pc, SSB_PCICORE_ARBCTL, val); |
319 | udelay(1); /* Assertion time demanded by the PCI standard */ | 340 | udelay(1); /* Assertion time demanded by the PCI standard */ |
320 | 341 | ||
321 | /*TODO cardbus mode */ | 342 | if (pc->dev->bus->has_cardbus_slot) { |
343 | ssb_dprintk(KERN_INFO PFX "CardBus slot detected\n"); | ||
344 | pc->cardbusmode = 1; | ||
345 | /* GPIO 1 resets the bridge */ | ||
346 | ssb_gpio_out(pc->dev->bus, 1, 1); | ||
347 | ssb_gpio_outen(pc->dev->bus, 1, 1); | ||
348 | pcicore_write16(pc, SSB_PCICORE_SPROM(0), | ||
349 | pcicore_read16(pc, SSB_PCICORE_SPROM(0)) | ||
350 | | 0x0400); | ||
351 | } | ||
322 | 352 | ||
323 | /* 64MB I/O window */ | 353 | /* 64MB I/O window */ |
324 | pcicore_write32(pc, SSB_PCICORE_SBTOPCI0, | 354 | pcicore_write32(pc, SSB_PCICORE_SBTOPCI0, |
@@ -344,7 +374,8 @@ static void ssb_pcicore_init_hostmode(struct ssb_pcicore *pc) | |||
344 | /* Ok, ready to run, register it to the system. | 374 | /* Ok, ready to run, register it to the system. |
345 | * The following needs change, if we want to port hostmode | 375 | * The following needs change, if we want to port hostmode |
346 | * to non-MIPS platform. */ | 376 | * to non-MIPS platform. */ |
347 | set_io_port_base((unsigned long)ioremap_nocache(SSB_PCI_MEM, 0x04000000)); | 377 | ssb_pcicore_controller.io_map_base = (unsigned long)ioremap_nocache(SSB_PCI_MEM, 0x04000000); |
378 | set_io_port_base(ssb_pcicore_controller.io_map_base); | ||
348 | /* Give some time to the PCI controller to configure itself with the new | 379 | /* Give some time to the PCI controller to configure itself with the new |
349 | * values. Not waiting at this point causes crashes of the machine. */ | 380 | * values. Not waiting at this point causes crashes of the machine. */ |
350 | mdelay(10); | 381 | mdelay(10); |
diff --git a/drivers/ssb/embedded.c b/drivers/ssb/embedded.c new file mode 100644 index 000000000000..d3ade821555c --- /dev/null +++ b/drivers/ssb/embedded.c | |||
@@ -0,0 +1,132 @@ | |||
1 | /* | ||
2 | * Sonics Silicon Backplane | ||
3 | * Embedded systems support code | ||
4 | * | ||
5 | * Copyright 2005-2008, Broadcom Corporation | ||
6 | * Copyright 2006-2008, Michael Buesch <mb@bu3sch.de> | ||
7 | * | ||
8 | * Licensed under the GNU/GPL. See COPYING for details. | ||
9 | */ | ||
10 | |||
11 | #include <linux/ssb/ssb.h> | ||
12 | #include <linux/ssb/ssb_embedded.h> | ||
13 | |||
14 | #include "ssb_private.h" | ||
15 | |||
16 | |||
17 | int ssb_watchdog_timer_set(struct ssb_bus *bus, u32 ticks) | ||
18 | { | ||
19 | if (ssb_chipco_available(&bus->chipco)) { | ||
20 | ssb_chipco_watchdog_timer_set(&bus->chipco, ticks); | ||
21 | return 0; | ||
22 | } | ||
23 | if (ssb_extif_available(&bus->extif)) { | ||
24 | ssb_extif_watchdog_timer_set(&bus->extif, ticks); | ||
25 | return 0; | ||
26 | } | ||
27 | return -ENODEV; | ||
28 | } | ||
29 | |||
30 | u32 ssb_gpio_in(struct ssb_bus *bus, u32 mask) | ||
31 | { | ||
32 | unsigned long flags; | ||
33 | u32 res = 0; | ||
34 | |||
35 | spin_lock_irqsave(&bus->gpio_lock, flags); | ||
36 | if (ssb_chipco_available(&bus->chipco)) | ||
37 | res = ssb_chipco_gpio_in(&bus->chipco, mask); | ||
38 | else if (ssb_extif_available(&bus->extif)) | ||
39 | res = ssb_extif_gpio_in(&bus->extif, mask); | ||
40 | else | ||
41 | SSB_WARN_ON(1); | ||
42 | spin_unlock_irqrestore(&bus->gpio_lock, flags); | ||
43 | |||
44 | return res; | ||
45 | } | ||
46 | EXPORT_SYMBOL(ssb_gpio_in); | ||
47 | |||
48 | u32 ssb_gpio_out(struct ssb_bus *bus, u32 mask, u32 value) | ||
49 | { | ||
50 | unsigned long flags; | ||
51 | u32 res = 0; | ||
52 | |||
53 | spin_lock_irqsave(&bus->gpio_lock, flags); | ||
54 | if (ssb_chipco_available(&bus->chipco)) | ||
55 | res = ssb_chipco_gpio_out(&bus->chipco, mask, value); | ||
56 | else if (ssb_extif_available(&bus->extif)) | ||
57 | res = ssb_extif_gpio_out(&bus->extif, mask, value); | ||
58 | else | ||
59 | SSB_WARN_ON(1); | ||
60 | spin_unlock_irqrestore(&bus->gpio_lock, flags); | ||
61 | |||
62 | return res; | ||
63 | } | ||
64 | EXPORT_SYMBOL(ssb_gpio_out); | ||
65 | |||
66 | u32 ssb_gpio_outen(struct ssb_bus *bus, u32 mask, u32 value) | ||
67 | { | ||
68 | unsigned long flags; | ||
69 | u32 res = 0; | ||
70 | |||
71 | spin_lock_irqsave(&bus->gpio_lock, flags); | ||
72 | if (ssb_chipco_available(&bus->chipco)) | ||
73 | res = ssb_chipco_gpio_outen(&bus->chipco, mask, value); | ||
74 | else if (ssb_extif_available(&bus->extif)) | ||
75 | res = ssb_extif_gpio_outen(&bus->extif, mask, value); | ||
76 | else | ||
77 | SSB_WARN_ON(1); | ||
78 | spin_unlock_irqrestore(&bus->gpio_lock, flags); | ||
79 | |||
80 | return res; | ||
81 | } | ||
82 | EXPORT_SYMBOL(ssb_gpio_outen); | ||
83 | |||
84 | u32 ssb_gpio_control(struct ssb_bus *bus, u32 mask, u32 value) | ||
85 | { | ||
86 | unsigned long flags; | ||
87 | u32 res = 0; | ||
88 | |||
89 | spin_lock_irqsave(&bus->gpio_lock, flags); | ||
90 | if (ssb_chipco_available(&bus->chipco)) | ||
91 | res = ssb_chipco_gpio_control(&bus->chipco, mask, value); | ||
92 | spin_unlock_irqrestore(&bus->gpio_lock, flags); | ||
93 | |||
94 | return res; | ||
95 | } | ||
96 | EXPORT_SYMBOL(ssb_gpio_control); | ||
97 | |||
98 | u32 ssb_gpio_intmask(struct ssb_bus *bus, u32 mask, u32 value) | ||
99 | { | ||
100 | unsigned long flags; | ||
101 | u32 res = 0; | ||
102 | |||
103 | spin_lock_irqsave(&bus->gpio_lock, flags); | ||
104 | if (ssb_chipco_available(&bus->chipco)) | ||
105 | res = ssb_chipco_gpio_intmask(&bus->chipco, mask, value); | ||
106 | else if (ssb_extif_available(&bus->extif)) | ||
107 | res = ssb_extif_gpio_intmask(&bus->extif, mask, value); | ||
108 | else | ||
109 | SSB_WARN_ON(1); | ||
110 | spin_unlock_irqrestore(&bus->gpio_lock, flags); | ||
111 | |||
112 | return res; | ||
113 | } | ||
114 | EXPORT_SYMBOL(ssb_gpio_intmask); | ||
115 | |||
116 | u32 ssb_gpio_polarity(struct ssb_bus *bus, u32 mask, u32 value) | ||
117 | { | ||
118 | unsigned long flags; | ||
119 | u32 res = 0; | ||
120 | |||
121 | spin_lock_irqsave(&bus->gpio_lock, flags); | ||
122 | if (ssb_chipco_available(&bus->chipco)) | ||
123 | res = ssb_chipco_gpio_polarity(&bus->chipco, mask, value); | ||
124 | else if (ssb_extif_available(&bus->extif)) | ||
125 | res = ssb_extif_gpio_polarity(&bus->extif, mask, value); | ||
126 | else | ||
127 | SSB_WARN_ON(1); | ||
128 | spin_unlock_irqrestore(&bus->gpio_lock, flags); | ||
129 | |||
130 | return res; | ||
131 | } | ||
132 | EXPORT_SYMBOL(ssb_gpio_polarity); | ||
diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c index 9028ed5715a1..bedb2b4ee9d2 100644 --- a/drivers/ssb/main.c +++ b/drivers/ssb/main.c | |||
@@ -557,6 +557,7 @@ static int ssb_fetch_invariants(struct ssb_bus *bus, | |||
557 | goto out; | 557 | goto out; |
558 | memcpy(&bus->boardinfo, &iv.boardinfo, sizeof(iv.boardinfo)); | 558 | memcpy(&bus->boardinfo, &iv.boardinfo, sizeof(iv.boardinfo)); |
559 | memcpy(&bus->sprom, &iv.sprom, sizeof(iv.sprom)); | 559 | memcpy(&bus->sprom, &iv.sprom, sizeof(iv.sprom)); |
560 | bus->has_cardbus_slot = iv.has_cardbus_slot; | ||
560 | out: | 561 | out: |
561 | return err; | 562 | return err; |
562 | } | 563 | } |
@@ -569,6 +570,9 @@ static int ssb_bus_register(struct ssb_bus *bus, | |||
569 | 570 | ||
570 | spin_lock_init(&bus->bar_lock); | 571 | spin_lock_init(&bus->bar_lock); |
571 | INIT_LIST_HEAD(&bus->list); | 572 | INIT_LIST_HEAD(&bus->list); |
573 | #ifdef CONFIG_SSB_EMBEDDED | ||
574 | spin_lock_init(&bus->gpio_lock); | ||
575 | #endif | ||
572 | 576 | ||
573 | /* Powerup the bus */ | 577 | /* Powerup the bus */ |
574 | err = ssb_pci_xtal(bus, SSB_GPIO_XTAL | SSB_GPIO_PLL, 1); | 578 | err = ssb_pci_xtal(bus, SSB_GPIO_XTAL | SSB_GPIO_PLL, 1); |