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 <[email protected]>:
> 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 <[email protected]>:
>>> 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 <[email protected]>
+ * Copyright (C) 2005-2007 Michael Buesch <[email protected]>
+ * Copyright (C) 2005 Martin Langer <[email protected]>
+ * Copyright (C) 2005 Stefano Brivio <[email protected]>
+@@ -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
[email protected]
https://lists.openwrt.org/mailman/listinfo/openwrt-devel