Index: target/linux/brcm47xx/patches-2.6.32/952-ai-scan.patch
===================================================================
--- target/linux/brcm47xx/patches-2.6.32/952-ai-scan.patch	(revision 0)
+++ target/linux/brcm47xx/patches-2.6.32/952-ai-scan.patch	(revision 0)
@@ -0,0 +1,527 @@
+Index: linux-2.6.32.9/drivers/ssb/scan.c
+===================================================================
+--- linux-2.6.32.9.orig/drivers/ssb/scan.c	2010-04-14 10:43:32.000000000 +0200
++++ linux-2.6.32.9/drivers/ssb/scan.c	2010-04-23 00:28:32.391526154 +0200
+@@ -2,6 +2,7 @@
+  * Sonics Silicon Backplane
+  * Bus scanning
+  *
++ * Copyright (C) 2010 Bernhard Loos <bernhardloos@googlemail.com>
+  * Copyright (C) 2005-2007 Michael Buesch <mb@bu3sch.de>
+  * Copyright (C) 2005 Martin Langer <martin-langer@gmx.de>
+  * Copyright (C) 2005 Stefano Brivio <st3@riseup.net>
+@@ -216,6 +217,8 @@
+ 	case SSB_BUSTYPE_SSB:
+ 	case SSB_BUSTYPE_PCMCIA:
+ 		iounmap(bus->mmio);
++		if (bus->ai_mmio)
++			iounmap(bus->ai_mmio);
+ 		break;
+ 	case SSB_BUSTYPE_PCI:
+ #ifdef CONFIG_SSB_PCIHOST
+@@ -228,6 +231,7 @@
+ 		break;
+ 	}
+ 	bus->mmio = NULL;
++	bus->ai_mmio = NULL;
+ 	bus->mapped_device = NULL;
+ }
+ 
+@@ -276,15 +280,278 @@
+ 	return 0;
+ }
+ 
++/* returns 0 if the core is ok and -1 if the core should be ignored */
++static int ssb_bus_check_core(struct ssb_device *dev, int *nr_80211_cores, int corenum)
++{
++	struct ssb_bus *bus = dev->bus;
++  
++	ssb_dprintk(KERN_INFO PFX
++		    "Core %d found: %s "
++		    "(cc 0x%03X, rev 0x%02X, vendor 0x%04X)\n",
++		    corenum, ssb_core_name(dev->id.coreid),
++		    dev->id.coreid, dev->id.revision, dev->id.vendor);
++
++	switch (dev->id.coreid) {
++	case SSB_DEV_80211:
++		(*nr_80211_cores)++;
++		if (*nr_80211_cores > 1) {
++			if (!we_support_multiple_80211_cores(bus)) {
++				ssb_dprintk(KERN_INFO PFX "Ignoring additional "
++					    "802.11 core\n");
++				return -1;
++			}
++		}
++		break;
++	case SSB_DEV_EXTIF:
++#ifdef CONFIG_SSB_DRIVER_EXTIF
++		if (bus->extif.dev) {
++			ssb_printk(KERN_WARNING PFX
++				   "WARNING: Multiple EXTIFs found\n");
++			break;
++		}
++		bus->extif.dev = dev;
++#endif /* CONFIG_SSB_DRIVER_EXTIF */
++		break;
++	case SSB_DEV_CHIPCOMMON:
++		if (bus->chipco.dev) {
++			ssb_printk(KERN_WARNING PFX
++				   "WARNING: Multiple ChipCommon found\n");
++			break;
++		}
++		bus->chipco.dev = dev;
++		break;
++	case SSB_DEV_MIPS:
++	case SSB_DEV_MIPS_3302:
++#ifdef CONFIG_SSB_DRIVER_MIPS
++		if (bus->mipscore.dev) {
++			ssb_printk(KERN_WARNING PFX
++				   "WARNING: Multiple MIPS cores found\n");
++			break;
++		}
++		bus->mipscore.dev = dev;
++#endif /* CONFIG_SSB_DRIVER_MIPS */
++		break;
++	case SSB_DEV_PCI:
++	case SSB_DEV_PCIE:
++#ifdef CONFIG_SSB_DRIVER_PCICORE
++		if (bus->bustype == SSB_BUSTYPE_PCI) {
++			/* Ignore PCI cores on PCI-E cards.
++			 * Ignore PCI-E cores on PCI cards. */
++			if (dev->id.coreid == SSB_DEV_PCI) {
++				if (bus->host_pci->is_pcie)
++					return -1;
++			} else {
++				if (!bus->host_pci->is_pcie)
++					return -1;
++			}
++		}
++		if (bus->pcicore.dev) {
++			ssb_printk(KERN_WARNING PFX
++				   "WARNING: Multiple PCI(E) cores found\n");
++			break;
++		}
++		bus->pcicore.dev = dev;
++#endif /* CONFIG_SSB_DRIVER_PCICORE */
++		break;
++	default:
++		break;
++	}
++	return 0;
++}
++
++static int ssb_scan_sb(struct ssb_bus *bus)
++{
++	int i, dev_i, err;
++	struct ssb_device *dev;
++	int nr_80211_cores = 0;
++	u32 idhi;
++
++	/* Fetch basic information about each core/device */
++	for (i = 0, dev_i = 0; i < bus->nr_devices; i++) {
++		err = scan_switchcore(bus, i);
++		if (err)
++			return err;
++		dev = &(bus->devices[dev_i]);
++
++		idhi = scan_read32(bus, i, SSB_IDHIGH);
++		dev->id.coreid = (idhi & SSB_IDHIGH_CC) >> SSB_IDHIGH_CC_SHIFT;
++		dev->id.revision = (idhi & SSB_IDHIGH_RCLO);
++		dev->id.revision |= (idhi & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT;
++		dev->id.vendor = (idhi & SSB_IDHIGH_VC) >> SSB_IDHIGH_VC_SHIFT;
++		dev->core_index = i;
++		dev->bus = bus;
++		dev->ops = bus->ops;
++
++		if (ssb_bus_check_core(dev, &nr_80211_cores, i) < 0)
++			continue;
++		
++		dev_i++;
++	}
++	bus->nr_devices = dev_i;
++
++	return 0;
++}
++
++static u32
++get_erom_ent(struct ssb_bus *bus, u32 **eromptr, u32 mask, u32 match)
++{
++	u32 ent;
++
++	while (1) {
++		ent = readl(*eromptr);
++		(*eromptr)++;
++
++		if (mask == 0)
++			break;
++
++		if ((ent & SSB_EROM_VALID) == 0)
++			continue;
++
++		if (ent == (SSB_EROM_END | SSB_EROM_VALID))
++			break;
++
++		if ((ent & mask) == match)
++			break;
++	}
++	return ent;
++}
++
++static u32
++get_adress_space_descriptor(struct ssb_bus *bus, u32 **eromptr, uint st, u32 *addrl, u32 *sizel)
++{
++	u32 asd, sz, szd, expect;
++	
++	expect = SSB_EROM_ASD | st;
++	if (st == SSB_EROM_ASD_ST_SWRAP)
++		expect |= 1 << SSB_EROM_ASD_SP_SHIFT;
++	
++	asd = get_erom_ent(bus, eromptr, SSB_EROM_ASD_SP_MASK | SSB_EROM_TAG | SSB_EROM_ASD_ST_MASK, expect);
++
++	*addrl = asd & SSB_EROM_ASD_ADDR_MASK;
++
++	/* *addrh = get_erom_ent(sih, eromptr, 0, 0); 
++	   64bit addresses are not supported */
++	BUG_ON(asd & SSB_EROM_ASD_AG32);
++
++	sz = asd & SSB_EROM_ASD_SZ_MASK;
++	if (sz == SSB_EROM_ASD_SZ_SZD) {
++		szd = get_erom_ent(bus, eromptr, 0, 0);
++		*sizel = szd & SSB_EROM_ASD_SZ_MASK;
++	} else
++		*sizel = SSB_EROM_ASD_SZ_BASE << (sz >> SSB_EROM_ASD_SZ_SHIFT);
++
++	return asd;
++}
++
++static int ssb_scan_ai(struct ssb_bus *bus)
++{
++	int i = 0, dev_i, err;
++	struct ssb_device *dev;
++	int nr_80211_cores = 0;
++	void __iomem *mmio;
++	u32 __iomem *eromptr;
++	u32 __iomem *eromend;
++
++
++	mmio = ioremap(SSB_AI_BASE, SSB_CORE_SIZE * bus->nr_devices);
++	if (!mmio)
++		return -ENOMEM;
++	bus->ai_mmio = mmio;
++
++	eromptr = ioremap(scan_read32(bus, 0, SSB_CHIPCO_EROM), SSB_CORE_SIZE);
++	if (!eromptr)
++		return -ENOMEM;
++
++	eromend = eromptr + SSB_CORE_SIZE / sizeof(u32);
++
++	while ((i < bus->nr_devices) && (eromptr < eromend)) {
++		u32 cia, cib, asd, sizel, addrl, nmw;
++
++		err = scan_switchcore(bus, i);
++		if (err)
++			return err;
++		dev = &(bus->devices[dev_i]);
++
++
++		cia = get_erom_ent(bus, &eromptr, SSB_EROM_TAG, SSB_EROM_CI);
++		if (cia == (SSB_EROM_END | SSB_EROM_VALID)) {
++			ssb_dprintk(KERN_INFO PFX "Found END of erom after %d cores\n", dev_i);
++			if (dev_i != bus->nr_devices) {
++				ssb_printk(KERN_WARNING PFX "Expected %d cores but got %d\n", bus->nr_devices, dev_i);
++			}
++			break;
++		}
++		cib = get_erom_ent(bus, &eromptr, 0, 0);
++		if ((cib & SSB_EROM_TAG) != SSB_EROM_CI) {
++			ssb_printk(KERN_ERR PFX "CIA not followed by CIB\n");
++			return -EIO;
++		}
++
++		dev->id.coreid = (cia & SSB_EROM_CIA_CID_MASK) >> SSB_EROM_CIA_CID_SHIFT;
++		dev->id.vendor = (cia & SSB_EROM_CIA_MFG_MASK) >> SSB_EROM_CIA_MFG_SHIFT;
++		dev->id.revision = (cib & SSB_EROM_CIB_REV_MASK) >> SSB_EROM_CIB_REV_SHIFT;
++		dev->core_index = dev_i;
++		dev->bus = bus;
++		dev->ops = bus->ops;
++
++		nmw = cib & SSB_EROM_CIB_NMW_MASK;
++		if (((dev->id.coreid == SSB_DEV_DEFAULT) && (dev->id.vendor == SSB_VENDOR_ARM)) ||
++			(nmw == 0 && (cib & SSB_EROM_CIB_NSW_MASK) == 0) ||
++			((cib & SSB_EROM_CIB_NSP_MASK) == 0)) {
++			continue;
++		}
++
++		/* see if it is a bridge */
++		if ((SSB_EROM_ASD_ST_MASK & get_erom_ent(bus, &eromptr, SSB_EROM_TAG, SSB_EROM_ASD)) ==
++				SSB_EROM_ASD_ST_BRIDGE)
++			continue;/* don't record bridges */
++		else
++			eromptr--;
++
++		/* First Slave Address Descriptor should be port 0:
++		 * the main register space for the core
++		 */
++		asd = get_adress_space_descriptor(bus, &eromptr, SSB_EROM_ASD_ST_SLAVE, &addrl, &sizel);
++		if (sizel != SSB_CORE_SIZE || addrl != SSB_ENUM_BASE + SSB_CORE_SIZE * dev_i) {
++			ssb_printk(KERN_ERR PFX "Malformed or unsupported register address space descriptor for core %d:\n"
++									"\texpected 0x%x, got 0x%x, size 0x%x\n",
++									dev_i, SSB_ENUM_BASE + SSB_CORE_SIZE * dev_i, addrl, sizel);
++			return -EIO;
++		}
++
++		if (nmw)
++			asd = get_adress_space_descriptor(bus, &eromptr, SSB_EROM_ASD_ST_MWRAP, &addrl, &sizel);
++		else
++			asd = get_adress_space_descriptor(bus, &eromptr, SSB_EROM_ASD_ST_SWRAP, &addrl, &sizel);
++
++		if (sizel != SSB_CORE_SIZE || addrl != SSB_AI_BASE + SSB_CORE_SIZE * dev_i) {
++			ssb_printk(KERN_ERR PFX "Malformed or unsupported ai address space descriptor for core %d:\n"
++									"\texpected 0x%x, got 0x%x, size 0x%x\n",
++									dev_i, SSB_AI_BASE + SSB_CORE_SIZE * dev_i, addrl, sizel);
++			return -EIO;
++		}
++
++		if (ssb_bus_check_core(dev, &nr_80211_cores, i) < 0)
++			continue;
++
++		dev_i++;
++	}
++	bus->nr_devices = dev_i;
++	
++	if (eromptr >= eromend)
++		ssb_printk(KERN_WARNING PFX "Reached end of erom without finding END");
++
++	return 0;
++}
++
++
+ int ssb_bus_scan(struct ssb_bus *bus,
+ 		 unsigned long baseaddr)
+ {
+ 	int err = -ENOMEM;
+ 	void __iomem *mmio;
+-	u32 idhi, cc, rev, tmp;
+-	int dev_i, i;
+-	struct ssb_device *dev;
+-	int nr_80211_cores = 0;
++	u32 tmp, chiptype = SSB_CHIPCO_TYPE_SB;
++	bool have_chipcommon = true;
+ 
+ 	mmio = ssb_ioremap(bus, baseaddr);
+ 	if (!mmio)
+@@ -295,13 +562,13 @@
+ 	if (err)
+ 		goto err_unmap;
+ 
+-	idhi = scan_read32(bus, 0, SSB_IDHIGH);
+-	cc = (idhi & SSB_IDHIGH_CC) >> SSB_IDHIGH_CC_SHIFT;
+-	rev = (idhi & SSB_IDHIGH_RCLO);
+-	rev |= (idhi & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT;
++	/* this may break, if the first core isn't a chipcommon core,
++	   but we need to know, if this is an ai bus or not. */
++	if (SSB_DEV_CHIPCOMMON != (scan_read32(bus, 0, SSB_IDHIGH) & SSB_IDHIGH_CC) >> SSB_IDHIGH_CC_SHIFT)
++		have_chipcommon = false;
+ 
+ 	bus->nr_devices = 0;
+-	if (cc == SSB_DEV_CHIPCOMMON) {
++	if (have_chipcommon) {
+ 		tmp = scan_read32(bus, 0, SSB_CHIPCO_CHIPID);
+ 
+ 		bus->chip_id = (tmp & SSB_CHIPCO_IDMASK);
+@@ -309,7 +576,8 @@
+ 				SSB_CHIPCO_REVSHIFT;
+ 		bus->chip_package = (tmp & SSB_CHIPCO_PACKMASK) >>
+ 				    SSB_CHIPCO_PACKSHIFT;
+-		if (rev >= 4) {
++		chiptype = tmp & SSB_CHIPCO_TYPE_MASK;
++		if (bus->chip_rev >= 4) {
+ 			bus->nr_devices = (tmp & SSB_CHIPCO_NRCORESMASK) >>
+ 					  SSB_CHIPCO_NRCORESSHIFT;
+ 		}
+@@ -339,7 +607,6 @@
+ 		/* Now that we know the number of cores,
+ 		 * remap the whole IO space for all cores.
+ 		 */
+-		err = -ENOMEM;
+ 		iounmap(mmio);
+ 		mmio = ioremap(baseaddr, SSB_CORE_SIZE * bus->nr_devices);
+ 		if (!mmio)
+@@ -347,102 +614,23 @@
+ 		bus->mmio = mmio;
+ 	}
+ 
+-	/* Fetch basic information about each core/device */
+-	for (i = 0, dev_i = 0; i < bus->nr_devices; i++) {
+-		err = scan_switchcore(bus, i);
+-		if (err)
+-			goto err_unmap;
+-		dev = &(bus->devices[dev_i]);
+-
+-		idhi = scan_read32(bus, i, SSB_IDHIGH);
+-		dev->id.coreid = (idhi & SSB_IDHIGH_CC) >> SSB_IDHIGH_CC_SHIFT;
+-		dev->id.revision = (idhi & SSB_IDHIGH_RCLO);
+-		dev->id.revision |= (idhi & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT;
+-		dev->id.vendor = (idhi & SSB_IDHIGH_VC) >> SSB_IDHIGH_VC_SHIFT;
+-		dev->core_index = i;
+-		dev->bus = bus;
+-		dev->ops = bus->ops;
+-
+-		ssb_dprintk(KERN_INFO PFX
+-			    "Core %d found: %s "
+-			    "(cc 0x%03X, rev 0x%02X, vendor 0x%04X)\n",
+-			    i, ssb_core_name(dev->id.coreid),
+-			    dev->id.coreid, dev->id.revision, dev->id.vendor);
+-
+-		switch (dev->id.coreid) {
+-		case SSB_DEV_80211:
+-			nr_80211_cores++;
+-			if (nr_80211_cores > 1) {
+-				if (!we_support_multiple_80211_cores(bus)) {
+-					ssb_dprintk(KERN_INFO PFX "Ignoring additional "
+-						    "802.11 core\n");
+-					continue;
+-				}
+-			}
++	switch (chiptype) {
++		case SSB_CHIPCO_TYPE_SB:
++			err = ssb_scan_sb(bus);
+ 			break;
+-		case SSB_DEV_EXTIF:
+-#ifdef CONFIG_SSB_DRIVER_EXTIF
+-			if (bus->extif.dev) {
+-				ssb_printk(KERN_WARNING PFX
+-					   "WARNING: Multiple EXTIFs found\n");
+-				break;
+-			}
+-			bus->extif.dev = dev;
+-#endif /* CONFIG_SSB_DRIVER_EXTIF */
+-			break;
+-		case SSB_DEV_CHIPCOMMON:
+-			if (bus->chipco.dev) {
+-				ssb_printk(KERN_WARNING PFX
+-					   "WARNING: Multiple ChipCommon found\n");
+-				break;
+-			}
+-			bus->chipco.dev = dev;
+-			break;
+-		case SSB_DEV_MIPS:
+-		case SSB_DEV_MIPS_3302:
+-#ifdef CONFIG_SSB_DRIVER_MIPS
+-			if (bus->mipscore.dev) {
+-				ssb_printk(KERN_WARNING PFX
+-					   "WARNING: Multiple MIPS cores found\n");
+-				break;
+-			}
+-			bus->mipscore.dev = dev;
+-#endif /* CONFIG_SSB_DRIVER_MIPS */
+-			break;
+-		case SSB_DEV_PCI:
+-		case SSB_DEV_PCIE:
+-#ifdef CONFIG_SSB_DRIVER_PCICORE
+-			if (bus->bustype == SSB_BUSTYPE_PCI) {
+-				/* Ignore PCI cores on PCI-E cards.
+-				 * Ignore PCI-E cores on PCI cards. */
+-				if (dev->id.coreid == SSB_DEV_PCI) {
+-					if (bus->host_pci->is_pcie)
+-						continue;
+-				} else {
+-					if (!bus->host_pci->is_pcie)
+-						continue;
+-				}
+-			}
+-			if (bus->pcicore.dev) {
+-				ssb_printk(KERN_WARNING PFX
+-					   "WARNING: Multiple PCI(E) cores found\n");
+-				break;
+-			}
+-			bus->pcicore.dev = dev;
+-#endif /* CONFIG_SSB_DRIVER_PCICORE */
++		case SSB_CHIPCO_TYPE_AI:
++			err = ssb_scan_ai(bus);
+ 			break;
+ 		default:
+-			break;
+-		}
+-
+-		dev_i++;
++			ssb_printk(KERN_ERR PFX "Unsupported chiptype 0x%x\n", chiptype);
++			err = -ENOSYS;
+ 	}
+-	bus->nr_devices = dev_i;
+ 
+-	err = 0;
+-out:
+-	return err;
++	if (err == 0)
++		return 0;
++
+ err_unmap:
+ 	ssb_iounmap(bus);
+-	goto out;
++out:
++	return err;
+ }
+Index: linux-2.6.32.9/include/linux/ssb/ssb.h
+===================================================================
+--- linux-2.6.32.9.orig/include/linux/ssb/ssb.h	2010-04-20 08:44:00.000000000 +0200
++++ linux-2.6.32.9/include/linux/ssb/ssb.h	2010-04-22 22:10:30.367411110 +0200
+@@ -273,6 +273,7 @@
+ struct ssb_bus {
+ 	/* The MMIO area. */
+ 	void __iomem *mmio;
++	void __iomem *ai_mmio;
+ 
+ 	const struct ssb_bus_ops *ops;
+ 
+Index: linux-2.6.32.9/include/linux/ssb/ssb_driver_chipcommon.h
+===================================================================
+--- linux-2.6.32.9.orig/include/linux/ssb/ssb_driver_chipcommon.h	2010-04-14 10:08:18.000000000 +0200
++++ linux-2.6.32.9/include/linux/ssb/ssb_driver_chipcommon.h	2010-04-20 10:06:14.366218585 +0200
+@@ -23,6 +23,9 @@
+ #define  SSB_CHIPCO_PACKSHIFT		20
+ #define  SSB_CHIPCO_NRCORESMASK		0x0F000000
+ #define  SSB_CHIPCO_NRCORESSHIFT	24
++#define  SSB_CHIPCO_TYPE_MASK		0xf0000000
++#define SSB_CHIPCO_TYPE_SB				0
++#define SSB_CHIPCO_TYPE_AI				0x10000000
+ #define SSB_CHIPCO_CAP	 		0x0004		/* Capabilities */
+ #define  SSB_CHIPCO_CAP_NRUART		0x00000003	/* # of UARTs */
+ #define  SSB_CHIPCO_CAP_MIPSEB		0x00000004	/* MIPS in BigEndian Mode */
+@@ -169,6 +172,7 @@
+ #define  SSB_CHIPCO_SYSCLKCTL_CLKDIV	0xFFFF0000	/* ClkDiv  (ILP = 1/(4+divisor)) */
+ #define  SSB_CHIPCO_SYSCLKCTL_CLKDIV_SHIFT	16
+ #define SSB_CHIPCO_CLKSTSTR		0x00C4		/* Rev >= 3 only */
++#define SSB_CHIPCO_EROM				0xFC	/* erom for ai socs */
+ #define SSB_CHIPCO_PCMCIA_CFG		0x0100
+ #define SSB_CHIPCO_PCMCIA_MEMWAIT	0x0104
+ #define SSB_CHIPCO_PCMCIA_ATTRWAIT	0x0108
+@@ -297,6 +301,28 @@
+ #define  SSB_PMU1_PLLCTL5_CLKDRV		0xFFFFFF00 /* clk drv */
+ #define  SSB_PMU1_PLLCTL5_CLKDRV_SHIFT		8
+ 
++/* PMU rev 5 (& 6) */
++#define	SSB_PMU5_PLL_P1P2_OFF		0
++#define	 SSB_PMU5_PLL_P1_MASK		0x0f000000
++#define	 SSB_PMU5_PLL_P1_SHIFT		24
++#define	 SSB_PMU5_PLL_P2_MASK		0x00f00000
++#define	 SSB_PMU5_PLL_P2_SHIFT		20
++#define	SSB_PMU5_PLL_M14_OFF		1
++#define	 SSB_PMU5_PLL_MDIV_MASK		0x000000ff
++#define	 SSB_PMU5_PLL_MDIV_WIDTH	8
++#define	SSB_PMU5_PLL_NM5_OFF		2
++#define	 SSB_PMU5_PLL_NDIV_MASK		0xfff00000
++#define	 SSB_PMU5_PLL_NDIV_SHIFT		20
++#define	SSB_PMU5_PLL_FMAB_OFF		3
++#define	 SSB_PMU5_PLL_MRAT_MASK		0xf0000000
++#define	 SSB_PMU5_PLL_MRAT_SHIFT		28
++#define	 SSB_PMU5_PLL_ABRAT_MASK		0x08000000
++#define	 SSB_PMU5_PLL_ABRAT_SHIFT		27
++#define	 SSB_PMU5_PLL_FDIV_MASK		0x07ffffff
++#define	SSB_PMU5_PLL_PLLCTL_OFF		4
++#define	SSB_PMU5_PLL_PCHI_OFF		5
++#define	 SSB_PMU5_PLL_PCHI_MASK		0x0000003f
++
+ /* BCM4312 PLL resource numbers. */
+ #define SSB_PMURES_4312_SWITCHER_BURST		0
+ #define SSB_PMURES_4312_SWITCHER_PWM    	1
Index: target/linux/brcm47xx/patches-2.6.32/953-ai-enabledev.patch
===================================================================
--- target/linux/brcm47xx/patches-2.6.32/953-ai-enabledev.patch	(revision 0)
+++ target/linux/brcm47xx/patches-2.6.32/953-ai-enabledev.patch	(revision 0)
@@ -0,0 +1,191 @@
+Index: linux-2.6.32.9/drivers/ssb/main.c
+===================================================================
+--- linux-2.6.32.9.orig/drivers/ssb/main.c	2010-04-14 10:25:20.000000000 +0200
++++ linux-2.6.32.9/drivers/ssb/main.c	2010-04-20 12:45:03.982689054 +0200
+@@ -50,6 +50,14 @@
+ static void ssb_buses_lock(void);
+ static void ssb_buses_unlock(void);
+ 
++static int ssb_device_is_enabled_ai(struct ssb_device *dev);
++static void ssb_device_enable_ai(struct ssb_device *dev, u32 core_specific_flags);
++static void ssb_device_disable_ai(struct ssb_device *dev, u32 core_specific_flags);
++static int ssb_device_is_enabled_sb(struct ssb_device *dev);
++static void ssb_device_enable_sb(struct ssb_device *dev, u32 core_specific_flags);
++static void ssb_device_disable_sb(struct ssb_device *dev, u32 core_specific_flags);
++
++
+ 
+ #ifdef CONFIG_SSB_PCIHOST
+ struct ssb_bus *ssb_pci_dev_to_bus(struct pci_dev *pdev)
+@@ -746,6 +754,22 @@
+ #endif
+ };
+ 
++void ssb_ai_write32(struct ssb_device *dev, u16 offset, u32 value)
++{
++	struct ssb_bus *bus = dev->bus;
++	
++	offset += dev->core_index * SSB_CORE_SIZE;
++	return writel(value, bus->ai_mmio + offset);
++}
++
++u32 ssb_ai_read32(struct ssb_device *dev, u16 offset)
++{
++	struct ssb_bus *bus = dev->bus;
++	
++	offset += dev->core_index * SSB_CORE_SIZE;
++	return readl(bus->ai_mmio + offset);
++}
++
+ static int ssb_fetch_invariants(struct ssb_bus *bus,
+ 				ssb_invariants_func_t get_invariants)
+ {
+@@ -791,7 +815,17 @@
+ 	err = ssb_bus_scan(bus, baseaddr);
+ 	if (err)
+ 		goto err_sdio_exit;
+-
++	
++	if (bus->ai_mmio) {
++		bus->device_is_enabled = ssb_device_is_enabled_ai;
++		bus->device_enable = ssb_device_enable_ai;
++		bus->device_disable = ssb_device_disable_ai;
++	} else {
++		bus->device_is_enabled = ssb_device_is_enabled_sb;
++		bus->device_enable = ssb_device_enable_sb;
++		bus->device_disable = ssb_device_disable_sb;
++	}
++	
+ 	/* Init PCI-host device (if any) */
+ 	err = ssb_pci_init(bus);
+ 	if (err)
+@@ -1130,7 +1164,41 @@
+ 	return (SSB_TMSLOW_REJECT_22 | SSB_TMSLOW_REJECT_23);
+ }
+ 
+-int ssb_device_is_enabled(struct ssb_device *dev)
++static int ssb_device_is_enabled_ai(struct ssb_device *dev)
++{
++	return (ssb_ai_read32(dev, SSB_AI_RESETCTRL) & SSB_AI_RESETCTRL_RESET) == 0;
++}
++
++static void ssb_ai_ioctl_write(struct ssb_device *dev, u32 flags)
++{
++	u32 dummy;
++	ssb_ai_write32(dev, SSB_AI_IOCTRL, flags);
++	dummy = ssb_ai_read32(dev, SSB_AI_IOCTRL);
++	udelay(1);
++}
++
++static void ssb_device_enable_ai(struct ssb_device *dev, u32 core_specific_flags)
++{
++	ssb_device_disable_ai(dev, core_specific_flags);
++	
++	ssb_ai_ioctl_write(dev, core_specific_flags | SSB_CF_FGC | SSB_CF_CLOCK_EN);
++	ssb_ai_write32(dev, SSB_AI_RESETCTRL, 0);
++	udelay(1);
++
++	ssb_ai_ioctl_write(dev, core_specific_flags | SSB_CF_CLOCK_EN);
++}
++
++static void ssb_device_disable_ai(struct ssb_device *dev, u32 core_specific_flags)
++{
++	if (ssb_ai_read32(dev, SSB_AI_RESETCTRL) & SSB_AI_RESETCTRL_RESET)
++		return;
++	ssb_ai_ioctl_write(dev, core_specific_flags);
++	udelay(9);
++	ssb_ai_write32(dev, SSB_AI_RESETCTRL, SSB_AI_RESETCTRL_RESET);
++	udelay(1);
++}
++
++static int ssb_device_is_enabled_sb(struct ssb_device *dev)
+ {
+ 	u32 val;
+ 	u32 reject;
+@@ -1141,7 +1209,6 @@
+ 
+ 	return (val == SSB_TMSLOW_CLOCK);
+ }
+-EXPORT_SYMBOL(ssb_device_is_enabled);
+ 
+ static void ssb_flush_tmslow(struct ssb_device *dev)
+ {
+@@ -1155,11 +1222,11 @@
+ 	udelay(1);
+ }
+ 
+-void ssb_device_enable(struct ssb_device *dev, u32 core_specific_flags)
++static void ssb_device_enable_sb(struct ssb_device *dev, u32 core_specific_flags)
+ {
+ 	u32 val;
+ 
+-	ssb_device_disable(dev, core_specific_flags);
++	ssb_device_disable_sb(dev, core_specific_flags);
+ 	ssb_write32(dev, SSB_TMSLOW,
+ 		    SSB_TMSLOW_RESET | SSB_TMSLOW_CLOCK |
+ 		    SSB_TMSLOW_FGC | core_specific_flags);
+@@ -1184,7 +1251,6 @@
+ 		    core_specific_flags);
+ 	ssb_flush_tmslow(dev);
+ }
+-EXPORT_SYMBOL(ssb_device_enable);
+ 
+ /* Wait for a bit in a register to get set or unset.
+  * timeout is in units of ten-microseconds */
+@@ -1212,7 +1278,7 @@
+ 	return -ETIMEDOUT;
+ }
+ 
+-void ssb_device_disable(struct ssb_device *dev, u32 core_specific_flags)
++static void ssb_device_disable_sb(struct ssb_device *dev, u32 core_specific_flags)
+ {
+ 	u32 reject;
+ 
+@@ -1234,7 +1300,6 @@
+ 		    core_specific_flags);
+ 	ssb_flush_tmslow(dev);
+ }
+-EXPORT_SYMBOL(ssb_device_disable);
+ 
+ u32 ssb_dma_translation(struct ssb_device *dev)
+ {
+Index: linux-2.6.32.9/include/linux/ssb/ssb.h
+===================================================================
+--- linux-2.6.32.9.orig/include/linux/ssb/ssb.h	2010-04-20 08:45:02.000000000 +0200
++++ linux-2.6.32.9/include/linux/ssb/ssb.h	2010-04-20 12:41:29.937387824 +0200
+@@ -352,6 +352,10 @@
+ 	bool powered_up;
+ 	int power_warn_count;
+ #endif /* DEBUG */
++
++	int (*device_is_enabled)(struct ssb_device *dev);
++	void (*device_enable)(struct ssb_device *dev, u32 core_specific_flags);
++	void (*device_disable)(struct ssb_device *dev, u32 core_specific_flags);
+ };
+ 
+ enum ssb_quirks {
+@@ -412,12 +416,21 @@
+ extern u32 ssb_clockspeed(struct ssb_bus *bus);
+ 
+ /* Is the device enabled in hardware? */
+-int ssb_device_is_enabled(struct ssb_device *dev);
++static inline int ssb_device_is_enabled(struct ssb_device *dev)
++{
++	return dev->bus->device_is_enabled(dev);
++}
+ /* Enable a device and pass device-specific SSB_TMSLOW flags.
+  * If no device-specific flags are available, use 0. */
+-void ssb_device_enable(struct ssb_device *dev, u32 core_specific_flags);
++static inline void ssb_device_enable(struct ssb_device *dev, u32 core_specific_flags)
++{
++	return dev->bus->device_enable(dev, core_specific_flags);
++}
+ /* Disable a device in hardware and pass SSB_TMSLOW flags (if any). */
+-void ssb_device_disable(struct ssb_device *dev, u32 core_specific_flags);
++static inline void ssb_device_disable(struct ssb_device *dev, u32 core_specific_flags)
++{
++	return dev->bus->device_disable(dev, core_specific_flags);
++}
+ 
+ 
+ /* Device MMIO register read/write functions. */
