diff options
author | Peter Denison <openwrt@marshadder.org> | 2007-06-21 20:10:50 +0000 |
---|---|---|
committer | Peter Denison <openwrt@marshadder.org> | 2007-06-21 20:10:50 +0000 |
commit | 0f3100df555289b57b816f1fb767a9908bf862cd (patch) | |
tree | 3484c631f3eaea7fccab2fa15ffab748837f1709 /target/linux/brcm47xx-2.6/patches | |
parent | b94b11e11eee8b43ec951f46afc446bfaaebb87c (diff) | |
download | upstream-0f3100df555289b57b816f1fb767a9908bf862cd.tar.gz upstream-0f3100df555289b57b816f1fb767a9908bf862cd.tar.bz2 upstream-0f3100df555289b57b816f1fb767a9908bf862cd.zip |
brcm43xx: update SSB driver * files/ now contains the wireless-dev tree version * patches/210-ssb_merge is nbd's subsequent changes
SVN-Revision: 7691
Diffstat (limited to 'target/linux/brcm47xx-2.6/patches')
3 files changed, 755 insertions, 0 deletions
diff --git a/target/linux/brcm47xx-2.6/patches/200-b44_ssb_fixup.patch b/target/linux/brcm47xx-2.6/patches/200-b44_ssb_fixup.patch new file mode 100644 index 0000000000..816d7e18b6 --- /dev/null +++ b/target/linux/brcm47xx-2.6/patches/200-b44_ssb_fixup.patch @@ -0,0 +1,256 @@ +Index: linux-2.6.22-rc4/drivers/net/b44.c +=================================================================== +--- linux-2.6.22-rc4.orig/drivers/net/b44.c 2007-06-10 21:33:15.000000000 +0100 ++++ linux-2.6.22-rc4/drivers/net/b44.c 2007-06-10 21:33:23.000000000 +0100 +@@ -128,7 +128,7 @@ + unsigned long offset, + enum dma_data_direction dir) + { +- dma_sync_single_range_for_device(&sdev->dev, dma_base, ++ dma_sync_single_range_for_device(sdev->dev, dma_base, + offset & dma_desc_align_mask, + dma_desc_sync_size, dir); + } +@@ -138,7 +138,7 @@ + unsigned long offset, + enum dma_data_direction dir) + { +- dma_sync_single_range_for_cpu(&sdev->dev, dma_base, ++ dma_sync_single_range_for_cpu(sdev->dev, dma_base, + offset & dma_desc_align_mask, + dma_desc_sync_size, dir); + } +@@ -563,7 +563,7 @@ + + BUG_ON(skb == NULL); + +- dma_unmap_single(&bp->sdev->dev, ++ dma_unmap_single(bp->sdev->dev, + pci_unmap_addr(rp, mapping), + skb->len, + DMA_TO_DEVICE); +@@ -603,7 +603,7 @@ + if (skb == NULL) + return -ENOMEM; + +- mapping = dma_map_single(&bp->sdev->dev, skb->data, ++ mapping = dma_map_single(bp->sdev->dev, skb->data, + RX_PKT_BUF_SZ, + DMA_FROM_DEVICE); + +@@ -613,18 +613,18 @@ + mapping + RX_PKT_BUF_SZ > DMA_30BIT_MASK) { + /* Sigh... */ + if (!dma_mapping_error(mapping)) +- dma_unmap_single(&bp->sdev->dev, mapping, RX_PKT_BUF_SZ,DMA_FROM_DEVICE); ++ dma_unmap_single(bp->sdev->dev, mapping, RX_PKT_BUF_SZ,DMA_FROM_DEVICE); + dev_kfree_skb_any(skb); + skb = __dev_alloc_skb(RX_PKT_BUF_SZ,GFP_DMA); + if (skb == NULL) + return -ENOMEM; +- mapping = dma_map_single(&bp->sdev->dev, skb->data, ++ mapping = dma_map_single(bp->sdev->dev, skb->data, + RX_PKT_BUF_SZ, + DMA_FROM_DEVICE); + if (dma_mapping_error(mapping) || + mapping + RX_PKT_BUF_SZ > DMA_30BIT_MASK) { + if (!dma_mapping_error(mapping)) +- dma_unmap_single(&bp->sdev->dev, mapping, RX_PKT_BUF_SZ,DMA_FROM_DEVICE); ++ dma_unmap_single(bp->sdev->dev, mapping, RX_PKT_BUF_SZ,DMA_FROM_DEVICE); + dev_kfree_skb_any(skb); + return -ENOMEM; + } +@@ -702,7 +702,7 @@ + dest_idx * sizeof(dest_desc), + DMA_BIDIRECTIONAL); + +- dma_sync_single_for_device(&bp->sdev->dev, le32_to_cpu(src_desc->addr), ++ dma_sync_single_for_device(bp->sdev->dev, le32_to_cpu(src_desc->addr), + RX_PKT_BUF_SZ, + DMA_FROM_DEVICE); + } +@@ -724,7 +724,7 @@ + struct rx_header *rh; + u16 len; + +- dma_sync_single_for_cpu(&bp->sdev->dev, map, ++ dma_sync_single_for_cpu(bp->sdev->dev, map, + RX_PKT_BUF_SZ, + DMA_FROM_DEVICE); + rh = (struct rx_header *) skb->data; +@@ -758,7 +758,7 @@ + skb_size = b44_alloc_rx_skb(bp, cons, bp->rx_prod); + if (skb_size < 0) + goto drop_it; +- dma_unmap_single(&bp->sdev->dev, map, ++ dma_unmap_single(bp->sdev->dev, map, + skb_size, DMA_FROM_DEVICE); + /* Leave out rx_header */ + skb_put(skb, len+bp->rx_offset); +@@ -931,22 +931,22 @@ + goto err_out; + } + +- mapping = dma_map_single(&bp->sdev->dev, skb->data, len, DMA_TO_DEVICE); ++ mapping = dma_map_single(bp->sdev->dev, skb->data, len, DMA_TO_DEVICE); + if (dma_mapping_error(mapping) || mapping + len > DMA_30BIT_MASK) { + /* Chip can't handle DMA to/from >1GB, use bounce buffer */ + if (!dma_mapping_error(mapping)) +- dma_unmap_single(&bp->sdev->dev, mapping, len, DMA_TO_DEVICE); ++ dma_unmap_single(bp->sdev->dev, mapping, len, DMA_TO_DEVICE); + + bounce_skb = __dev_alloc_skb(TX_PKT_BUF_SZ, + GFP_ATOMIC|GFP_DMA); + if (!bounce_skb) + goto err_out; + +- mapping = dma_map_single(&bp->sdev->dev, bounce_skb->data, ++ mapping = dma_map_single(bp->sdev->dev, bounce_skb->data, + len, DMA_TO_DEVICE); + if (dma_mapping_error(mapping) || mapping + len > DMA_30BIT_MASK) { + if (!dma_mapping_error(mapping)) +- dma_unmap_single(&bp->sdev->dev, mapping, ++ dma_unmap_single(bp->sdev->dev, mapping, + len, DMA_TO_DEVICE); + dev_kfree_skb_any(bounce_skb); + goto err_out; +@@ -1046,7 +1046,7 @@ + + if (rp->skb == NULL) + continue; +- dma_unmap_single(&bp->sdev->dev, ++ dma_unmap_single(bp->sdev->dev, + pci_unmap_addr(rp, mapping), + RX_PKT_BUF_SZ, + DMA_FROM_DEVICE); +@@ -1060,7 +1060,7 @@ + + if (rp->skb == NULL) + continue; +- dma_unmap_single(&bp->sdev->dev, ++ dma_unmap_single(bp->sdev->dev, + pci_unmap_addr(rp, mapping), + rp->skb->len, + DMA_TO_DEVICE); +@@ -1085,12 +1085,12 @@ + memset(bp->tx_ring, 0, B44_TX_RING_BYTES); + + if (bp->flags & B44_FLAG_RX_RING_HACK) +- dma_sync_single_for_device(&bp->sdev->dev, bp->rx_ring_dma, ++ dma_sync_single_for_device(bp->sdev->dev, bp->rx_ring_dma, + DMA_TABLE_BYTES, + DMA_BIDIRECTIONAL); + + if (bp->flags & B44_FLAG_TX_RING_HACK) +- dma_sync_single_for_device(&bp->sdev->dev, bp->tx_ring_dma, ++ dma_sync_single_for_device(bp->sdev->dev, bp->tx_ring_dma, + DMA_TABLE_BYTES, + DMA_TO_DEVICE); + +@@ -1112,24 +1112,24 @@ + bp->tx_buffers = NULL; + if (bp->rx_ring) { + if (bp->flags & B44_FLAG_RX_RING_HACK) { +- dma_unmap_single(&bp->sdev->dev, bp->rx_ring_dma, ++ dma_unmap_single(bp->sdev->dev, bp->rx_ring_dma, + DMA_TABLE_BYTES, + DMA_BIDIRECTIONAL); + kfree(bp->rx_ring); + } else +- dma_free_coherent(&bp->sdev->dev, DMA_TABLE_BYTES, ++ dma_free_coherent(bp->sdev->dev, DMA_TABLE_BYTES, + bp->rx_ring, bp->rx_ring_dma); + bp->rx_ring = NULL; + bp->flags &= ~B44_FLAG_RX_RING_HACK; + } + if (bp->tx_ring) { + if (bp->flags & B44_FLAG_TX_RING_HACK) { +- dma_unmap_single(&bp->sdev->dev, bp->tx_ring_dma, ++ dma_unmap_single(bp->sdev->dev, bp->tx_ring_dma, + DMA_TABLE_BYTES, + DMA_TO_DEVICE); + kfree(bp->tx_ring); + } else +- dma_free_coherent(&bp->sdev->dev, DMA_TABLE_BYTES, ++ dma_free_coherent(bp->sdev->dev, DMA_TABLE_BYTES, + bp->tx_ring, bp->tx_ring_dma); + bp->tx_ring = NULL; + bp->flags &= ~B44_FLAG_TX_RING_HACK; +@@ -1155,7 +1155,7 @@ + goto out_err; + + size = DMA_TABLE_BYTES; +- bp->rx_ring = dma_alloc_coherent(&bp->sdev->dev, size, &bp->rx_ring_dma, GFP_ATOMIC); ++ bp->rx_ring = dma_alloc_coherent(bp->sdev->dev, size, &bp->rx_ring_dma, GFP_ATOMIC); + if (!bp->rx_ring) { + /* Allocation may have failed due to pci_alloc_consistent + insisting on use of GFP_DMA, which is more restrictive +@@ -1167,7 +1167,7 @@ + if (!rx_ring) + goto out_err; + +- rx_ring_dma = dma_map_single(&bp->sdev->dev, rx_ring, ++ rx_ring_dma = dma_map_single(bp->sdev->dev, rx_ring, + DMA_TABLE_BYTES, + DMA_BIDIRECTIONAL); + +@@ -1182,7 +1182,7 @@ + bp->flags |= B44_FLAG_RX_RING_HACK; + } + +- bp->tx_ring = dma_alloc_coherent(&bp->sdev->dev, size, &bp->tx_ring_dma, GFP_ATOMIC); ++ bp->tx_ring = dma_alloc_coherent(bp->sdev->dev, size, &bp->tx_ring_dma, GFP_ATOMIC); + if (!bp->tx_ring) { + /* Allocation may have failed due to dma_alloc_coherent + insisting on use of GFP_DMA, which is more restrictive +@@ -1194,7 +1194,7 @@ + if (!tx_ring) + goto out_err; + +- tx_ring_dma = dma_map_single(&bp->sdev->dev, tx_ring, ++ tx_ring_dma = dma_map_single(bp->sdev->dev, tx_ring, + DMA_TABLE_BYTES, + DMA_TO_DEVICE); + +@@ -2314,13 +2314,13 @@ + + dev = alloc_etherdev(sizeof(*bp)); + if (!dev) { +- dev_err(&sdev->dev, "Etherdev alloc failed, aborting.\n"); ++ dev_err(sdev->dev, "Etherdev alloc failed, aborting.\n"); + err = -ENOMEM; + goto out; + } + + SET_MODULE_OWNER(dev); +- SET_NETDEV_DEV(dev,&sdev->dev); ++ SET_NETDEV_DEV(dev,sdev->dev); + + /* No interesting netdevice features in this card... */ + dev->features |= 0; +@@ -2358,7 +2358,7 @@ + + err = b44_get_invariants(bp); + if (err) { +- dev_err(&sdev->dev, ++ dev_err(sdev->dev, + "Problem fetching invariants of chip, aborting.\n"); + goto err_out_free_dev; + } +@@ -2379,7 +2379,7 @@ + + err = register_netdev(dev); + if (err) { +- dev_err(&sdev->dev, "Cannot register net device, aborting.\n"); ++ dev_err(sdev->dev, "Cannot register net device, aborting.\n"); + goto out; + } + +@@ -2458,7 +2458,6 @@ + rc = request_irq(dev->irq, b44_interrupt, IRQF_SHARED, dev->name, dev); + if (rc) { + printk(KERN_ERR PFX "%s: request_irq failed\n", dev->name); +- pci_disable_device(pdev); + return rc; + } + diff --git a/target/linux/brcm47xx-2.6/patches/205-ssb_integrate.patch b/target/linux/brcm47xx-2.6/patches/205-ssb_integrate.patch new file mode 100644 index 0000000000..67882454d8 --- /dev/null +++ b/target/linux/brcm47xx-2.6/patches/205-ssb_integrate.patch @@ -0,0 +1,78 @@ +Index: linux-2.6.22-rc4/drivers/usb/host/Kconfig +=================================================================== +--- linux-2.6.22-rc4.orig/drivers/usb/host/Kconfig 2007-06-10 21:32:11.000000000 +0100 ++++ linux-2.6.22-rc4/drivers/usb/host/Kconfig 2007-06-10 21:33:24.000000000 +0100 +@@ -142,6 +142,19 @@ + Enables support for PCI-bus plug-in USB controller cards. + If unsure, say Y. + ++config USB_OHCI_HCD_SSB ++ bool "OHCI support for the Broadcom SSB OHCI core (embedded systems only)" ++ depends on USB_OHCI_HCD && ((USB_OHCI_HCD=m && SSB) || (USB_OHCI_HCD=y && SSB=y)) && EXPERIMENTAL ++ default n ++ ---help--- ++ Support for the Sonics Silicon Backplane (SSB) attached ++ Broadcom USB OHCI core. ++ ++ This device is only present in some embedded devices with ++ Broadcom based SSB bus. ++ ++ If unsure, say N. ++ + config USB_OHCI_BIG_ENDIAN_DESC + bool + depends on USB_OHCI_HCD +Index: linux-2.6.22-rc4/drivers/usb/host/ohci-hcd.c +=================================================================== +--- linux-2.6.22-rc4.orig/drivers/usb/host/ohci-hcd.c 2007-06-10 21:32:11.000000000 +0100 ++++ linux-2.6.22-rc4/drivers/usb/host/ohci-hcd.c 2007-06-10 21:33:24.000000000 +0100 +@@ -920,11 +920,17 @@ + #define PS3_SYSTEM_BUS_DRIVER ps3_ohci_sb_driver + #endif + ++#ifdef CONFIG_USB_OHCI_HCD_SSB ++#include "ohci-ssb.c" ++#define SSB_OHCI_DRIVER ssb_ohci_driver ++#endif ++ + #if !defined(PCI_DRIVER) && \ + !defined(PLATFORM_DRIVER) && \ + !defined(OF_PLATFORM_DRIVER) && \ + !defined(SA1111_DRIVER) && \ +- !defined(PS3_SYSTEM_BUS_DRIVER) ++ !defined(PS3_SYSTEM_BUS_DRIVER) && \ ++ !defined(SSB_OHCI_DRIVER) + #error "missing bus glue for ohci-hcd" + #endif + +@@ -972,10 +978,20 @@ + goto error_pci; + #endif + ++#ifdef SSB_OHCI_DRIVER ++ retval = ssb_driver_register(&SSB_OHCI_DRIVER); ++ if (retval) ++ goto error_ssb; ++#endif ++ + return retval; + + /* Error path */ ++#ifdef SSB_OHCI_DRIVER ++ error_ssb: ++#endif + #ifdef PCI_DRIVER ++ pci_unregister_driver(&PCI_DRIVER); + error_pci: + #endif + #ifdef SA1111_DRIVER +@@ -1001,6 +1017,9 @@ + + static void __exit ohci_hcd_mod_exit(void) + { ++#ifdef SSB_OHCI_DRIVER ++ ssb_driver_unregister(&SSB_OHCI_DRIVER); ++#endif + #ifdef PCI_DRIVER + pci_unregister_driver(&PCI_DRIVER); + #endif diff --git a/target/linux/brcm47xx-2.6/patches/210-ssb_merge.patch b/target/linux/brcm47xx-2.6/patches/210-ssb_merge.patch new file mode 100644 index 0000000000..21986b3426 --- /dev/null +++ b/target/linux/brcm47xx-2.6/patches/210-ssb_merge.patch @@ -0,0 +1,421 @@ +Index: linux-2.6.22-rc4/drivers/ssb/driver_chipcommon.c +=================================================================== +--- linux-2.6.22-rc4.orig/drivers/ssb/driver_chipcommon.c 2007-06-10 21:32:11.000000000 +0100 ++++ linux-2.6.22-rc4/drivers/ssb/driver_chipcommon.c 2007-06-10 21:33:25.000000000 +0100 +@@ -264,6 +264,31 @@ + ssb_chipco_set_clockmode(cc, SSB_CLKMODE_FAST); + } + ++/* TODO: These two functions are a clear candidate for merging, but one gets ++ * the processor clock, and the other gets the bus clock. ++ */ ++void ssb_chipco_get_clockcpu(struct ssb_chipcommon *cc, ++ u32 *plltype, u32 *n, u32 *m) ++{ ++ *n = chipco_read32(cc, SSB_CHIPCO_CLOCK_N); ++ *plltype = (cc->capabilities & SSB_CHIPCO_CAP_PLLT); ++ switch (*plltype) { ++ case SSB_PLLTYPE_2: ++ case SSB_PLLTYPE_4: ++ case SSB_PLLTYPE_6: ++ case SSB_PLLTYPE_7: ++ *m = chipco_read32(cc, SSB_CHIPCO_CLOCK_MIPS); ++ break; ++ case SSB_PLLTYPE_3: ++ /* 5350 uses m2 to control mips */ ++ *m = chipco_read32(cc, SSB_CHIPCO_CLOCK_M2); ++ break; ++ default: ++ *m = chipco_read32(cc, SSB_CHIPCO_CLOCK_SB); ++ break; ++ } ++} ++ + void ssb_chipco_get_clockcontrol(struct ssb_chipcommon *cc, + u32 *plltype, u32 *n, u32 *m) + { +@@ -400,3 +425,13 @@ + return nr_ports; + } + #endif /* CONFIG_SSB_SERIAL */ ++ ++/* Set chip watchdog reset timer to fire in 'ticks' backplane cycles */ ++int ++ssb_chipco_watchdog(struct ssb_chipcommon *cc, uint ticks) ++{ ++ /* instant NMI */ ++ chipco_write32(cc, SSB_CHIPCO_WATCHDOG, ticks); ++ return 0; ++} ++EXPORT_SYMBOL(ssb_chipco_watchdog); +Index: linux-2.6.22-rc4/drivers/ssb/driver_mipscore.c +=================================================================== +--- linux-2.6.22-rc4.orig/drivers/ssb/driver_mipscore.c 2007-06-10 21:32:11.000000000 +0100 ++++ linux-2.6.22-rc4/drivers/ssb/driver_mipscore.c 2007-06-10 21:33:25.000000000 +0100 +@@ -4,6 +4,7 @@ + * + * Copyright 2005, Broadcom Corporation + * Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de> ++ * Copyright 2006, 2007, Felix Fietkau <nbd@openwrt.org> + * + * Licensed under the GNU/GPL. See COPYING for details. + */ +@@ -31,6 +32,16 @@ + ssb_write32(mcore->dev, offset, value); + } + ++static inline u32 extif_read32(struct ssb_extif *extif, u16 offset) ++{ ++ return ssb_read32(extif->dev, offset); ++} ++ ++static inline void extif_write32(struct ssb_extif *extif, u16 offset, u32 value) ++{ ++ ssb_write32(extif->dev, offset, value); ++} ++ + static const u32 ipsflag_irq_mask[] = { + 0, + SSB_IPSFLAG_IRQ1, +@@ -118,9 +129,9 @@ + } + + /* XXX: leave here or move into separate extif driver? */ +-static int ssb_extif_serial_init(struct ssb_device *dev, struct ssb_serial_ports *ports) ++static int ssb_extif_serial_init(struct ssb_extif *dev, struct ssb_serial_port *ports) + { +- ++ return 0; + } + + +@@ -174,23 +185,76 @@ + { + struct ssb_bus *bus = mcore->dev->bus; + ++ mcore->flash_buswidth = 2; + if (bus->chipco.dev) { + mcore->flash_window = 0x1c000000; +- mcore->flash_window_size = 0x800000; ++ mcore->flash_window_size = 0x02000000; ++ if ((ssb_read32(bus->chipco.dev, SSB_CHIPCO_FLASH_CFG) ++ & SSB_CHIPCO_CFG_DS16) == 0) ++ mcore->flash_buswidth = 1; + } else { + mcore->flash_window = 0x1fc00000; +- mcore->flash_window_size = 0x400000; ++ mcore->flash_window_size = 0x00400000; + } + } + ++static void ssb_extif_timing_init(struct ssb_extif *extif, u32 ns) ++{ ++ u32 tmp; ++ ++ /* Initialize extif so we can get to the LEDs and external UART */ ++ extif_write32(extif, SSB_EXTIF_PROG_CFG, SSB_EXTCFG_EN); ++ ++ /* Set timing for the flash */ ++ tmp = ceildiv(10, ns) << SSB_PROG_WCNT_3_SHIFT; ++ tmp |= ceildiv(40, ns) << SSB_PROG_WCNT_1_SHIFT; ++ tmp |= ceildiv(120, ns); ++ extif_write32(extif, SSB_EXTIF_PROG_WAITCNT, tmp); ++ ++ /* Set programmable interface timing for external uart */ ++ tmp = ceildiv(10, ns) << SSB_PROG_WCNT_3_SHIFT; ++ tmp |= ceildiv(20, ns) << SSB_PROG_WCNT_2_SHIFT; ++ tmp |= ceildiv(100, ns) << SSB_PROG_WCNT_1_SHIFT; ++ tmp |= ceildiv(120, ns); ++ extif_write32(extif, SSB_EXTIF_PROG_WAITCNT, tmp); ++} + +-static void ssb_cpu_clock(struct ssb_mipscore *mcore) ++static inline void ssb_extif_get_clockcontrol(struct ssb_extif *extif, ++ u32 *pll_type, u32 *n, u32 *m) + { ++ *pll_type = SSB_PLLTYPE_1; ++ *n = extif_read32(extif, SSB_EXTIF_CLOCK_N); ++ *m = extif_read32(extif, SSB_EXTIF_CLOCK_SB); + } + +-void ssb_mipscore_init(struct ssb_mipscore *mcore) ++u32 ssb_cpu_clock(struct ssb_mipscore *mcore) + { + struct ssb_bus *bus = mcore->dev->bus; ++ u32 pll_type, n, m, rate = 0; ++ ++ if (bus->extif.dev) { ++ ssb_extif_get_clockcontrol(&bus->extif, &pll_type, &n, &m); ++ } else if (bus->chipco.dev) { ++ ssb_chipco_get_clockcpu(&bus->chipco, &pll_type, &n, &m); ++ } else ++ return 0; ++ ++ if ((pll_type == SSB_PLLTYPE_5) || (bus->chip_id == 0x5365)) { ++ rate = 200000000; ++ } else { ++ rate = ssb_calc_clock_rate(pll_type, n, m); ++ } ++ ++ if (pll_type == SSB_PLLTYPE_6) { ++ rate *= 2; ++ } ++ ++ return rate; ++} ++ ++void ssb_mipscore_init(struct ssb_mipscore *mcore) ++{ ++ struct ssb_bus *bus; + struct ssb_device *dev; + unsigned long hz, ns; + unsigned int irq, i; +@@ -198,6 +262,8 @@ + if (!mcore->dev) + return; /* We don't have a MIPS core */ + ++ bus = mcore->dev->bus; ++ + ssb_dprintk(KERN_INFO PFX "Initializing MIPS core...\n"); + + hz = ssb_clockspeed(bus); +@@ -205,28 +271,9 @@ + hz = 100000000; + ns = 1000000000 / hz; + +-//TODO +-#if 0 +- if (have EXTIF) { +- /* Initialize extif so we can get to the LEDs and external UART */ +- W_REG(&eir->prog_config, CF_EN); +- +- /* Set timing for the flash */ +- tmp = CEIL(10, ns) << FW_W3_SHIFT; /* W3 = 10nS */ +- tmp = tmp | (CEIL(40, ns) << FW_W1_SHIFT); /* W1 = 40nS */ +- tmp = tmp | CEIL(120, ns); /* W0 = 120nS */ +- W_REG(&eir->prog_waitcount, tmp); /* 0x01020a0c for a 100Mhz clock */ +- +- /* Set programmable interface timing for external uart */ +- tmp = CEIL(10, ns) << FW_W3_SHIFT; /* W3 = 10nS */ +- tmp = tmp | (CEIL(20, ns) << FW_W2_SHIFT); /* W2 = 20nS */ +- tmp = tmp | (CEIL(100, ns) << FW_W1_SHIFT); /* W1 = 100nS */ +- tmp = tmp | CEIL(120, ns); /* W0 = 120nS */ +- W_REG(&eir->prog_waitcount, tmp); +- } +- else... chipcommon +-#endif +- if (bus->chipco.dev) ++ if (bus->extif.dev) ++ ssb_extif_timing_init(&bus->extif, ns); ++ else if (bus->chipco.dev) + ssb_chipco_timing_init(&bus->chipco, ns); + + /* Assign IRQs to all cores on the bus, start with irq line 2, because serial usually takes 1 */ +@@ -256,3 +303,5 @@ + ssb_mips_serial_init(mcore); + ssb_mips_flash_detect(mcore); + } ++ ++EXPORT_SYMBOL(ssb_mips_irq); +Index: linux-2.6.22-rc4/drivers/ssb/driver_pcicore.c +=================================================================== +--- linux-2.6.22-rc4.orig/drivers/ssb/driver_pcicore.c 2007-06-10 21:32:11.000000000 +0100 ++++ linux-2.6.22-rc4/drivers/ssb/driver_pcicore.c 2007-06-10 21:33:25.000000000 +0100 +@@ -93,6 +93,9 @@ + + /* Enable PCI bridge BAR1 prefetch and burst */ + pci_write_config_dword(dev, SSB_BAR1_CONTROL, 3); ++ ++ /* Make sure our latency is high enough to handle the devices behind us */ ++ pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0xa8); + } + DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, ssb_fixup_pcibridge); + +@@ -110,7 +113,7 @@ + + if (unlikely(pc->cardbusmode && dev > 1)) + goto out; +- if (bus == 0) { ++ if (bus == 0) {//FIXME busnumber ok? + /* Type 0 transaction */ + if (unlikely(dev >= SSB_PCI_SLOT_MAX)) + goto out; +@@ -224,7 +227,7 @@ + val = *((const u32 *)buf); + break; + } +- writel(*((const u32 *)buf), mmio); ++ writel(val, mmio); + + err = 0; + unmap: +@@ -307,6 +310,8 @@ + udelay(150); + val |= SSB_PCICORE_CTL_RST; /* Deassert RST# */ + pcicore_write32(pc, SSB_PCICORE_CTL, val); ++ val = SSB_PCICORE_ARBCTL_INTERN; ++ pcicore_write32(pc, SSB_PCICORE_ARBCTL, val); + udelay(1); + + //TODO cardbus mode +@@ -336,6 +341,7 @@ + * The following needs change, if we want to port hostmode + * to non-MIPS platform. */ + set_io_port_base((unsigned long)ioremap_nocache(SSB_PCI_MEM, 0x04000000)); ++ mdelay(300); + register_pci_controller(&ssb_pcicore_controller); + } + +Index: linux-2.6.22-rc4/include/linux/ssb/ssb_driver_chipcommon.h +=================================================================== +--- linux-2.6.22-rc4.orig/include/linux/ssb/ssb_driver_chipcommon.h 2007-06-10 21:32:11.000000000 +0100 ++++ linux-2.6.22-rc4/include/linux/ssb/ssb_driver_chipcommon.h 2007-06-10 21:33:25.000000000 +0100 +@@ -364,6 +364,8 @@ + extern void ssb_chipco_suspend(struct ssb_chipcommon *cc, pm_message_t state); + extern void ssb_chipco_resume(struct ssb_chipcommon *cc); + ++extern void ssb_chipco_get_clockcpu(struct ssb_chipcommon *cc, ++ u32 *plltype, u32 *n, u32 *m); + extern void ssb_chipco_get_clockcontrol(struct ssb_chipcommon *cc, + u32 *plltype, u32 *n, u32 *m); + extern void ssb_chipco_timing_init(struct ssb_chipcommon *cc, +@@ -378,6 +380,46 @@ + extern void ssb_chipco_set_clockmode(struct ssb_chipcommon *cc, + enum ssb_clkmode mode); + ++/* GPIO functions */ ++static inline u32 ssb_chipco_gpio_in(struct ssb_chipcommon *cc, ++ u32 mask) ++{ ++ return ssb_read32(cc->dev, SSB_CHIPCO_GPIOIN) & mask; ++} ++ ++static inline u32 ssb_chipco_gpio_out(struct ssb_chipcommon *cc, ++ u32 mask, u32 value) ++{ ++ return ssb_write32_masked(cc->dev, SSB_CHIPCO_GPIOOUT, mask, value); ++} ++ ++static inline u32 ssb_chipco_gpio_outen(struct ssb_chipcommon *cc, ++ u32 mask, u32 value) ++{ ++ return ssb_write32_masked(cc->dev, SSB_CHIPCO_GPIOOUTEN, mask, value); ++} ++ ++static inline u32 ssb_chipco_gpio_control(struct ssb_chipcommon *cc, ++ u32 mask, u32 value) ++{ ++ return ssb_write32_masked(cc->dev, SSB_CHIPCO_GPIOCTL, mask, value); ++} ++ ++static inline u32 ssb_chipco_gpio_intmask(struct ssb_chipcommon *cc, ++ u32 mask, u32 value) ++{ ++ return ssb_write32_masked(cc->dev, SSB_CHIPCO_GPIOIRQ, mask, value); ++} ++ ++static inline u32 ssb_chipco_gpio_polarity(struct ssb_chipcommon *cc, ++ u32 mask, u32 value) ++{ ++ return ssb_write32_masked(cc->dev, SSB_CHIPCO_GPIOPOL, mask, value); ++} ++/* TODO: GPIO reservation */ ++ ++extern int ssb_chipco_watchdog(struct ssb_chipcommon *cc, uint ticks); ++ + #ifdef CONFIG_SSB_SERIAL + extern int ssb_chipco_serial_init(struct ssb_chipcommon *cc, + struct ssb_serial_port *ports); +Index: linux-2.6.22-rc4/include/linux/ssb/ssb_driver_extif.h +=================================================================== +--- linux-2.6.22-rc4.orig/include/linux/ssb/ssb_driver_extif.h 2007-06-10 21:32:11.000000000 +0100 ++++ linux-2.6.22-rc4/include/linux/ssb/ssb_driver_extif.h 2007-06-10 21:33:25.000000000 +0100 +@@ -158,6 +158,36 @@ + /* watchdog */ + #define SSB_EXTIF_WATCHDOG_CLK 48000000 /* Hz */ + ++/* GPIO functions */ ++static inline u32 ssb_extif_gpio_in(struct ssb_extif *extif, ++ u32 mask) ++{ ++ return ssb_read32(extif->dev, SSB_EXTIF_GPIO_IN) & mask; ++} ++ ++static inline u32 ssb_extif_gpio_out(struct ssb_extif *extif, ++ u32 mask, u32 value) ++{ ++ return ssb_write32_masked(extif->dev, SSB_EXTIF_GPIO_OUT(0), mask, value); ++} ++ ++static inline u32 ssb_extif_gpio_outen(struct ssb_extif *extif, ++ u32 mask, u32 value) ++{ ++ return ssb_write32_masked(extif->dev, SSB_EXTIF_GPIO_OUTEN(0), mask, value); ++} ++ ++static inline u32 ssb_extif_gpio_polarity(struct ssb_extif *extif, ++ u32 mask, u32 value) ++{ ++ return ssb_write32_masked(extif->dev, SSB_EXTIF_GPIO_INTPOL, mask, value); ++} ++ ++static inline u32 ssb_extif_gpio_intmask(struct ssb_extif *extif, ++ u32 mask, u32 value) ++{ ++ return ssb_write32_masked(extif->dev, SSB_EXTIF_GPIO_INTMASK, mask, value); ++} + + #endif /* __KERNEL__ */ + #endif /* LINUX_SSB_EXTIFCORE_H_ */ +Index: linux-2.6.22-rc4/include/linux/ssb/ssb_driver_mips.h +=================================================================== +--- linux-2.6.22-rc4.orig/include/linux/ssb/ssb_driver_mips.h 2007-06-10 21:32:11.000000000 +0100 ++++ linux-2.6.22-rc4/include/linux/ssb/ssb_driver_mips.h 2007-06-10 21:33:25.000000000 +0100 +@@ -22,11 +22,13 @@ + int nr_serial_ports; + struct ssb_serial_port serial_ports[4]; + ++ int flash_buswidth; + u32 flash_window; + u32 flash_window_size; + }; + + extern void ssb_mipscore_init(struct ssb_mipscore *mcore); ++extern u32 ssb_cpu_clock(struct ssb_mipscore *mcore); + + extern unsigned int ssb_mips_irq(struct ssb_device *dev); + +Index: linux-2.6.22-rc4/include/linux/ssb/ssb.h +=================================================================== +--- linux-2.6.22-rc4.orig/include/linux/ssb/ssb.h 2007-06-10 21:32:11.000000000 +0100 ++++ linux-2.6.22-rc4/include/linux/ssb/ssb.h 2007-06-10 21:33:25.000000000 +0100 +@@ -263,6 +263,12 @@ + #define SSB_CHIPPACK_BCM4712M 2 /* Medium 225pin 4712 */ + #define SSB_CHIPPACK_BCM4712L 0 /* Large 340pin 4712 */ + ++static inline u16 ssb_read16(struct ssb_device *dev, u16 offset); ++static inline u32 ssb_read32(struct ssb_device *dev, u16 offset); ++static inline void ssb_write16(struct ssb_device *dev, u16 offset, u16 value); ++static inline void ssb_write32(struct ssb_device *dev, u16 offset, u32 value); ++static inline u32 ssb_write32_masked(struct ssb_device *dev, u16 offset, u32 mask, u32 value); ++ + #include <linux/ssb/ssb_driver_chipcommon.h> + #include <linux/ssb/ssb_driver_mips.h> + #include <linux/ssb/ssb_driver_extif.h> +@@ -369,6 +375,16 @@ + dev->ops->write32(dev, offset, value); + } + ++static inline u32 ssb_write32_masked(struct ssb_device *dev, ++ u16 offset, ++ u32 mask, ++ u32 value) ++{ ++ value &= mask; ++ value |= ssb_read32(dev, offset) & ~mask; ++ ssb_write32(dev, offset, value); ++ return value; ++} + + /* Translation (routing) bits that need to be ORed to DMA + * addresses before they are given to a device. */ |