Hello
Thank you for tracking this down.
Here are two new patches for the scan stuff, hopefully working now.

              Bernhard Loos

2010/5/15 Hauke Mehrtens <ha...@hauke-m.de>:
> Am 14.05.2010 00:25, schrieb Bernhard Loos:
>> Hello
>> Do you have any clue, what could produce b43? Because, after looking
>> at the code, I'm kinda at a loss, where this comes from. And do you
>> know, which patch exactly produces the problem?
>> I will split the patch up, but it may take a day or two, until I have
>> the time. Some of the other patches are possible also mixed up.
>> Your patch unfortunetly doesn't work as a general solution, because
>> the 4716 hangs, if any of the id registers is accessed.
>> Thanks again, for looking at this.
>>
>>      Bernhard
>>
>> 2010/5/13 Hauke Mehrtens <ha...@hauke-m.de>:
>>> Am 13.05.2010 20:54, schrieb Hauke Mehrtens:
>>>> Hi Bernhard,
>>>>
>>>> I have changed the code to do the same things it did before your changes
>>>> at that position. My patch is attached.
>>>>
>>>> With this patch all ssb Cores are found, but I get a oops in b43 driver
>>>> now. "Reserved instruction in kernel code"
>>>>
>>>> I have not activated symbols will do now. Here is the log for now:
>>>> http://hauke-m.de/fileadmin/openwrt/brcm47xx-log/boot-not-working2.log
>>>>
>>>> Could you please split 952-ai-scan.patch into two patches. One just
>>>> reorganizing the existing code without changing any functionality and
>>>> one adding the ai scan.
>>>>
>>>> Hauke
>>> Hi Bernhard,
>>>
>>> I get the following kernel oops with your patches:
>>>
>>> Reserved instruction in kernel code[#1]:
>>> ...
>>> Call Trace:
>>> [<80cc4908>] b43info+0x560/0x2754 [b43]
>>> [<8018a27c>] ssb_device_probe+0x44/0x80
>>> [<80167d24>] driver_probe_device+0x13c/0x28c
>>> [<800e78ec>] sysfs_create_dir+0x44/0x68
>>> [<8012b83c>] kobject_get+0x1c/0x30
>>> [<80167e74>] __driver_attach+0x0/0xa4
>>> [<80167ee0>] __driver_attach+0x6c/0xa4
>>> [<8012bf2c>] kobject_add_varg+0x28/0x78
>>> [<801673dc>] bus_for_each_dev+0x64/0xb4
>>> [<8012bfbc>] kobject_init_and_add+0x40/0x58
>>> [<80166b2c>] bus_add_driver+0xd0/0x274
>>> [<80056d20>] load_module+0x1980/0x1b4c
>>> [<80168290>] driver_register+0xe0/0x19c
>>> [<80ce8000>] init_module+0x0/0x70 [b43]
>>> [<80ce8020>] init_module+0x20/0x70 [b43]
>>> [<8000d650>] do_one_initcall+0x70/0x1f4
>>> [<800437f0>] blocking_notifier_call_chain+0x14/0x20
>>> [<80057408>] sys_init_module+0xe0/0x224
>>> [<80092924>] sys_close+0x9c/0xe4
>>> [<80003230>] stack_done+0x20/0x3c
>>>
>>> Full log:
>>> http://hauke-m.de/fileadmin/openwrt/brcm47xx-log/boot-not-working3.log
>>>
>>> Hauke
>>>
> Hi Bernhard,
>
> I found the cause of the problem. It was not in your patch series, but
> the some other openwrt parts. While building b43 from compat-wireless
> CONFIG_SSB_BLOCKIO was activated, when building ssb in the kernel is was
> deactivated. This causes the struct ssb_bus_ops to be different in ssb
> and b43. The Pointers to device_enable and so on are wrong. When they
> were called it jumped to somewhere else in the code.
> This problem is fixed in r21449 https://dev.openwrt.org/changeset/21449
>
> Now everything works for me like before with your patches when also
> adding the attached patch.
>
> In function ssb_bus_scan rev is not the same as bus->chip_rev.
>
> Hauke
>
Index: target/linux/brcm47xx/patches-2.6.32/952-ssb-scan_rework.patch
===================================================================
--- target/linux/brcm47xx/patches-2.6.32/952-ssb-scan_rework.patch	(revision 0)
+++ target/linux/brcm47xx/patches-2.6.32/952-ssb-scan_rework.patch	(revision 0)
@@ -0,0 +1,305 @@
+Index: linux-2.6.32.12/drivers/ssb/scan.c
+===================================================================
+--- linux-2.6.32.12.orig/drivers/ssb/scan.c	2010-05-11 18:04:00.000000000 +0200
++++ linux-2.6.32.12/drivers/ssb/scan.c	2010-05-11 18:14:32.810514610 +0200
+@@ -2,6 +2,7 @@
+  * Sonics Silicon Backplane
+  * Bus scanning
+  *
++ * Copyright (C) 2010 Bernhard Loos <bernhardl...@googlemail.com>
+  * Copyright (C) 2005-2007 Michael Buesch <m...@bu3sch.de>
+  * Copyright (C) 2005 Martin Langer <martin-lan...@gmx.de>
+  * Copyright (C) 2005 Stefano Brivio <s...@riseup.net>
+@@ -17,11 +18,6 @@
+ #include <linux/pci.h>
+ #include <linux/io.h>
+ 
+-#include <pcmcia/cs_types.h>
+-#include <pcmcia/cs.h>
+-#include <pcmcia/cistpl.h>
+-#include <pcmcia/ds.h>
+-
+ #include "ssb_private.h"
+ 
+ 
+@@ -276,15 +272,126 @@
+ 	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;
++  
++	printk(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:
++	case SSB_DEV_MIPS_74K:
++#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;
++}
++
+ 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;
++	bool have_chipcommon = true;
+ 
+ 	mmio = ssb_ioremap(bus, baseaddr);
+ 	if (!mmio)
+@@ -295,13 +402,11 @@
+ 	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;
+-
++	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,12 +414,9 @@
+ 				SSB_CHIPCO_REVSHIFT;
+ 		bus->chip_package = (tmp & SSB_CHIPCO_PACKMASK) >>
+ 				    SSB_CHIPCO_PACKSHIFT;
+-		if (rev >= 4) {
+-			bus->nr_devices = (tmp & SSB_CHIPCO_NRCORESMASK) >>
+-					  SSB_CHIPCO_NRCORESSHIFT;
+-		}
+-		tmp = scan_read32(bus, 0, SSB_CHIPCO_CAP);
+-		bus->chipco.capabilities = tmp;
++		bus->nr_devices = (tmp & SSB_CHIPCO_NRCORESMASK) >>
++				  SSB_CHIPCO_NRCORESSHIFT;
++		bus->chipco.capabilities = scan_read32(bus, 0, SSB_CHIPCO_CAP);
+ 	} else {
+ 		if (bus->bustype == SSB_BUSTYPE_PCI) {
+ 			bus->chip_id = pcidev_to_chipid(bus->host_pci);
+@@ -339,7 +441,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 +448,13 @@
+ 		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;
+-
+-		printk(KERN_DEBUG 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;
+-				}
+-			}
+-			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 */
+-			break;
+-		default:
+-			break;
+-		}
++	err = ssb_scan_sb(bus);
+ 
+-		dev_i++;
+-	}
+-	bus->nr_devices = dev_i;
++	if (err == 0)
++		return 0;
+ 
+-	err = 0;
+-out:
+-	return err;
+ err_unmap:
+ 	ssb_iounmap(bus);
+-	goto out;
++out:
++	return err;
+ }
Index: target/linux/brcm47xx/patches-2.6.32/953-ssb-ai_scan.patch
===================================================================
--- target/linux/brcm47xx/patches-2.6.32/953-ssb-ai_scan.patch	(revision 0)
+++ target/linux/brcm47xx/patches-2.6.32/953-ssb-ai_scan.patch	(revision 0)
@@ -0,0 +1,296 @@
+Index: linux-2.6.32.12/drivers/ssb/scan.c
+===================================================================
+--- linux-2.6.32.12.orig/drivers/ssb/scan.c	2010-05-11 18:35:20.052293905 +0200
++++ linux-2.6.32.12/drivers/ssb/scan.c	2010-05-11 18:44:01.135401247 +0200
+@@ -212,6 +212,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
+@@ -224,6 +226,7 @@
+ 		break;
+ 	}
+ 	bus->mmio = NULL;
++	bus->ai_mmio = NULL;
+ 	bus->mapped_device = NULL;
+ }
+ 
+@@ -385,12 +388,162 @@
+ 	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 dev_i = 0;
++	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 (eromptr < eromend) {
++		u32 cia, cib, asd, sizel, addrl, nmw, nsp;
++
++		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 = SSB_EROM_CIA_CID(cia);
++		dev->id.vendor = SSB_EROM_CIA_MFG(cia);
++		dev->id.revision = SSB_EROM_CIB_REV(cib);
++		dev->core_index = dev_i;
++		dev->bus = bus;
++		dev->ops = bus->ops;
++
++		nmw = SSB_EROM_CIB_NMW(cib);
++		nsp = SSB_EROM_CIB_NSP(cib);
++
++		if (((dev->id.coreid == SSB_DEV_DEFAULT) && (dev->id.vendor == SSB_VENDOR_ARM)) ||
++			(nmw == 0 && SSB_EROM_CIB_NSW(cib) == 0) || (nsp == 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, dev_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 tmp;
++	u32 tmp, chiptype = SSB_CHIPCO_TYPE_SB;
+ 	bool have_chipcommon = true;
+ 
+ 	mmio = ssb_ioremap(bus, baseaddr);
+@@ -402,8 +555,18 @@
+ 	if (err)
+ 		goto err_unmap;
+ 
+-	if (SSB_DEV_CHIPCOMMON != (scan_read32(bus, 0, SSB_IDHIGH) & SSB_IDHIGH_CC) >> SSB_IDHIGH_CC_SHIFT)
+-		have_chipcommon = false;
++	/* the problem goes like this:
++	 *   if we access the normal core id backplane registers on an ai soc, the thing hangs
++	 *   to figure out, if we have an ai soc, we have to look in a chipcommon register
++	 *   the 4710 doesn't have a chipcommon core_index
++	 *   but we can't figure this out without scanning the cores, and we don't know, if we
++	 *    have to use the ai or normal method
++	 *   all known ai socs have a 74k cpu, so let's take this as an indicator that we have a
++	 *    chipcommon core and hope for the best */
++	if (cpu_data[0].cputype != CPU_74K) {
++		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 (have_chipcommon) {
+@@ -414,6 +577,7 @@
+ 				SSB_CHIPCO_REVSHIFT;
+ 		bus->chip_package = (tmp & SSB_CHIPCO_PACKMASK) >>
+ 				    SSB_CHIPCO_PACKSHIFT;
++		chiptype = tmp & SSB_CHIPCO_TYPE_MASK;
+ 		bus->nr_devices = (tmp & SSB_CHIPCO_NRCORESMASK) >>
+ 				  SSB_CHIPCO_NRCORESSHIFT;
+ 		bus->chipco.capabilities = scan_read32(bus, 0, SSB_CHIPCO_CAP);
+@@ -448,7 +612,17 @@
+ 		bus->mmio = mmio;
+ 	}
+ 
+-	err = ssb_scan_sb(bus);
++	switch (chiptype) {
++		case SSB_CHIPCO_TYPE_SB:
++			err = ssb_scan_sb(bus);
++			break;
++		case SSB_CHIPCO_TYPE_AI:
++			err = ssb_scan_ai(bus);
++			break;
++		default:
++			ssb_printk(KERN_ERR PFX "Unsupported chiptype 0x%x\n", chiptype);
++			err = -ENOSYS;
++	}
+ 
+ 	if (err == 0)
+ 		return 0;
+Index: linux-2.6.32.12/include/linux/ssb/ssb.h
+===================================================================
+--- linux-2.6.32.12.orig/include/linux/ssb/ssb.h	2010-05-11 18:35:20.044100366 +0200
++++ linux-2.6.32.12/include/linux/ssb/ssb.h	2010-05-11 18:36:27.629653312 +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.12/include/linux/ssb/ssb_driver_chipcommon.h
+===================================================================
+--- linux-2.6.32.12.orig/include/linux/ssb/ssb_driver_chipcommon.h	2010-05-11 18:35:20.044100366 +0200
++++ linux-2.6.32.12/include/linux/ssb/ssb_driver_chipcommon.h	2010-05-11 18:36:27.629653312 +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 */
+@@ -170,6 +173,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
+@@ -298,6 +302,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
_______________________________________________
openwrt-devel mailing list
openwrt-devel@lists.openwrt.org
https://lists.openwrt.org/mailman/listinfo/openwrt-devel

Reply via email to