Return-path: Received: from mail-wy0-f174.google.com ([74.125.82.174]:51208 "EHLO mail-wy0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753552Ab1BIQtB (ORCPT ); Wed, 9 Feb 2011 11:49:01 -0500 Received: by wyb28 with SMTP id 28so377626wyb.19 for ; Wed, 09 Feb 2011 08:48:59 -0800 (PST) Message-ID: <4D52C5B3.1010605@lwfinger.net> Date: Wed, 09 Feb 2011 10:49:55 -0600 From: Larry Finger MIME-Version: 1.0 To: George Kashperko CC: linux-wireless Subject: Re: SSB AI support code ([RFC11/11] SSB add AI-bus support) References: <1297258590.17400.37.camel@dev.znau.edu.ua> <1297262780.18053.44.camel@dev.znau.edu.ua> In-Reply-To: <1297262780.18053.44.camel@dev.znau.edu.ua> Content-Type: text/plain; charset=windows-1252 Sender: linux-wireless-owner@vger.kernel.org List-ID: On 02/09/2011 08:46 AM, George Kashperko wrote: > From: Bernhard Loos > Add support for AI-style ssb bus. > Signed-off-by: George Kashperko > --- > drivers/ssb/Kconfig | 13 > drivers/ssb/Makefile | 1 > drivers/ssb/main.c | 2 > drivers/ssb/scan.c | 42 +- > drivers/ssb/ssb_ai.c | 381 ++++++++++++++++++++ > drivers/ssb/ssb_ai.h | 61 +++ > drivers/ssb/ssb_private.h | 9 > include/linux/ssb/ssb.h | 12 > include/linux/ssb/ssb_driver_chipcommon.h | 3 > 9 files changed, 516 insertions(+), 8 deletions(-) > --- linux-next-20110203.orig/drivers/ssb/Kconfig 2011-02-08 16:14:57.000000000 +0200 > +++ linux-next-20110203/drivers/ssb/Kconfig 2011-02-08 21:01:34.000000000 +0200 > @@ -9,7 +9,7 @@ menu "Sonics Silicon Backplane" > config SSB > tristate "Sonics Silicon Backplane support" > depends on SSB_POSSIBLE > - select SSB_BUS_SB > + select SSB_BUS_SB if !SSB_BUS_AI > help > Support for the Sonics Silicon Backplane bus. > You only need to enable this option, if you are > @@ -32,6 +32,17 @@ config SSB_BUS_SB > help > Sonics Silicon Backplane SB-style bus > > +config SSB_BUS_AI_POSSIBLE > + bool > + default y if SSB && EXPERIMENTAL > + > +config SSB_BUS_AI > + bool "AI style bus" > + depends on SSB_BUS_AI_POSSIBLE > + default n > + help > + Sonics Silicon Backplane AI-style bus > + > # Common SPROM support routines > config SSB_SPROM > bool > --- linux-next-20110203.orig/drivers/ssb/main.c 2011-02-08 18:55:26.000000000 +0200 > +++ linux-next-20110203/drivers/ssb/main.c 2011-02-08 21:01:34.000000000 +0200 > @@ -842,6 +842,8 @@ static const char *ssb_chipco_chiptype_n > switch (bus->chipco.chiptype) { > case SSB_CHIPCO_SB: > return "SB"; > + case SSB_CHIPCO_AI: > + return "AI"; > default: > return "UNKNOWN"; > } > --- linux-next-20110203.orig/drivers/ssb/Makefile 2011-02-08 16:14:57.000000000 +0200 > +++ linux-next-20110203/drivers/ssb/Makefile 2011-02-08 21:01:34.000000000 +0200 > @@ -1,6 +1,7 @@ > # core > ssb-y += main.o scan.o > ssb-$(CONFIG_SSB_BUS_SB) += ssb_sb.o > +ssb-$(CONFIG_SSB_BUS_AI) += ssb_ai.o > ssb-$(CONFIG_SSB_EMBEDDED) += embedded.o > ssb-$(CONFIG_SSB_SPROM) += sprom.o > > --- linux-next-20110203.orig/drivers/ssb/scan.c 2011-02-08 18:33:58.000000000 +0200 > +++ linux-next-20110203/drivers/ssb/scan.c 2011-02-08 21:01:34.000000000 +0200 > @@ -212,6 +212,10 @@ void ssb_iounmap(struct ssb_bus *bus) > case SSB_BUSTYPE_SSB: > case SSB_BUSTYPE_PCMCIA: > iounmap(bus->mmio); > +#ifdef CONFIG_SSB_BUS_AI > + if (bus->ai_mmio) > + iounmap(bus->ai_mmio); > +#endif > break; > case SSB_BUSTYPE_PCI: > #ifdef CONFIG_SSB_PCIHOST > @@ -364,18 +368,39 @@ int ssb_bus_check_core(struct ssb_device > /* Detect bus type and major bus information */ > static int ssb_bus_detect(struct ssb_bus *bus) > { > - u32 idhi, cc, rev, tmp; > + u32 idhi, rev, tmp; > + bool have_chipcommon = true; > enum ssb_chipco_chiptype chiptype = SSB_CHIPCO_SB; > > - 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; > + /* 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 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. > + */ > + rev = 0; > + if (cpu_data[0].cputype != CPU_74K) { > + idhi = scan_read32(bus, 0, SSB_IDHIGH); > + if (((idhi & SSB_IDHIGH_CC) >> SSB_IDHIGH_CC_SHIFT) != > + SSB_DEV_CHIPCOMMON) { > + have_chipcommon = false; > + } else { > + rev = (idhi & SSB_IDHIGH_RCLO); > + rev |= (idhi & SSB_IDHIGH_RCHI) >> > + SSB_IDHIGH_RCHI_SHIFT; > + } > + } > > bus->nr_devices = 0; > - if (cc == SSB_DEV_CHIPCOMMON) { > + if (have_chipcommon) { > tmp = scan_read32(bus, 0, SSB_CHIPCO_CHIPID); > > + chiptype = SSB_CHIPCO_TYPE(tmp); > bus->chip_id = (tmp & SSB_CHIPCO_IDMASK); > bus->chip_rev = (tmp & SSB_CHIPCO_REVMASK) >> > SSB_CHIPCO_REVSHIFT; > @@ -409,7 +434,7 @@ static int ssb_bus_detect(struct ssb_bus > } > > bus->chipco.chiptype = chiptype; > - return chiptype != SSB_CHIPCO_SB; > + return (chiptype != SSB_CHIPCO_SB && chiptype != SSB_CHIPCO_AI); > } > > int ssb_bus_scan(struct ssb_bus *bus, > @@ -451,6 +476,9 @@ int ssb_bus_scan(struct ssb_bus *bus, > case SSB_CHIPCO_SB: > err = ssb_bus_scan_sb(bus, baseaddr); > break; > + case SSB_CHIPCO_AI: > + err = ssb_bus_scan_ai(bus); > + break; > default: > SSB_WARN_ON(1); > err = -ENODEV; > --- linux-next-20110203.orig/drivers/ssb/ssb_ai.c 1970-01-01 03:00:00.000000000 +0300 > +++ linux-next-20110203/drivers/ssb/ssb_ai.c 2011-02-08 21:01:58.000000000 +0200 > @@ -0,0 +1,381 @@ > +/* > + * Sonics Silicon Backplane > + * AI Specific Subsystem core > + * > + * Copyright 2010, Bernhard Loos > + * Copyright (C) 2006 Broadcom Corporation. > + * > + * Licensed under the GNU/GPL. See COPYING for details. > + */ > + > +#include > +#include > +#include > + > +#include "ssb_private.h" > +#include "ssb_ai.h" > + > + > +static 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); > +} > + > +static 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); > +} > + > +/* The 47162a0 hangs when reading its registers */ > +static inline bool ssb_bcm47162a0_quirk(struct ssb_device *dev) > +{ > + return dev->bus->chip_id == 47162 && dev->bus->chip_rev == 0 && > + dev->id.coreid == SSB_DEV_MIPS_74K; > +} > + > +static void ssb_core_ctl_flags_ai(struct ssb_device *dev, u32 mask, > + u32 val, u32 *res) > +{ > + if (ssb_bcm47162a0_quirk(dev)) { > + printk("%s: Accessing MIPS DMP register (IOCTL) on 47162a0", > + __FUNCTION__); > + if (res) > + *res = 0; > + return; > + } > + > + if (mask || val) { > + u32 tmp = (ssb_ai_read32(dev, SSB_AI_IOCTL) & ~mask) | val; > + ssb_ai_write32(dev, SSB_AI_IOCTL, tmp); > + } > + > + if (res) > + *res = ssb_ai_read32(dev, SSB_AI_IOCTL); > +} > + > +static u32 ssb_core_state_flags_ai(struct ssb_device *dev, u32 mask, u32 val) > +{ > + if (ssb_bcm47162a0_quirk(dev)) { > + printk("%s: Accessing MIPS DMP register (IOSTAT) on 47162a0", > + __FUNCTION__); > + return 0; > + } > + > + if (mask || val) { > + u32 tmp = (ssb_ai_read32(dev, SSB_AI_IOSTAT) & ~mask) | val; > + ssb_ai_write32(dev, SSB_AI_IOSTAT, tmp); > + } > + > + return ssb_ai_read32(dev, SSB_AI_IOSTAT); > +} > + > +/* return -1 if no irq is supported */ > +static u32 ssb_irqflag_ai(struct ssb_device *dev) > +{ > + u32 flag; > + > + /* The 47162a0 hangs when reading its registers */ > + if (ssb_bcm47162a0_quirk(dev)) > + return dev->core_index; > + > + flag = ssb_ai_read32(dev, SSB_AI_oobselouta30); > + > + if (flag) > + return flag & 0x1F; > + else > + /* not irq supported */ > + return -1; > +} > + > +static int ssb_device_is_enabled_ai(struct ssb_device *dev) > +{ > + return (ssb_ai_read32(dev, SSB_AI_RESETCTL) & > + SSB_AI_RESETCTL_RESET) == 0; > +} > + > +static void ssb_ai_ioctl_write(struct ssb_device *dev, u32 flags) > +{ > + u32 dummy; > + ssb_ai_write32(dev, SSB_AI_IOCTL, flags); > + dummy = ssb_ai_read32(dev, SSB_AI_IOCTL); > + udelay(1); > +} > + > +static void ssb_device_disable_ai(struct ssb_device *dev, > + u32 core_specific_flags) > +{ > + SSB_WARN_ON(core_specific_flags & 0xFFFF0000); > + if (ssb_ai_read32(dev, SSB_AI_RESETCTL) & SSB_AI_RESETCTL_RESET) > + return; > + ssb_ai_ioctl_write(dev, core_specific_flags); > + udelay(9); > + ssb_ai_write32(dev, SSB_AI_RESETCTL, SSB_AI_RESETCTL_RESET); > + 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_CORECTL_FGC | > + SSB_CORECTL_CLOCK); > + ssb_ai_write32(dev, SSB_AI_RESETCTL, 0); > + udelay(1); > + > + ssb_ai_ioctl_write(dev, core_specific_flags | SSB_CORECTL_CLOCK); > +} > + > +static u32 ssb_admatch_base_ai(struct ssb_device *dev, u32 adm) > +{ > + switch (adm) { > + case SSB_ADMATCH0: > + return dev->coresba; > + case SSB_ADMATCH1: > + return dev->coresba2; > + default: > + printk(KERN_ERR PFX "Need to parse the erom again " > + "to find addr space %d\n", > + adm & SSB_ADM_TYPE); > + return 0; > + } > +} > + > +static u32 ssb_admatch_size_ai(struct ssb_device *dev, u32 adm) > +{ > + switch (adm) { > + case SSB_ADMATCH0: > + return dev->coresba_size; > + case SSB_ADMATCH1: > + return dev->coresba2_size; > + default: > + printk(KERN_ERR PFX "Need to parse the erom again " > + "to find addr space %d size\n", > + adm & SSB_ADM_TYPE); > + return 0; > + } > +} > + > +/* Ops for the plain SSB bus without a host-device (no PCI or PCMCIA). */ > +static struct ssb_bus_ops ssb_ops_ai = { > + .read8 = ssb_ssb_read8, > + .read16 = ssb_ssb_read16, > + .read32 = ssb_ssb_read32, > + .write8 = ssb_ssb_write8, > + .write16 = ssb_ssb_write16, > + .write32 = ssb_ssb_write32, > +#ifdef CONFIG_SSB_BLOCKIO > + .block_read = ssb_ssb_block_read, > + .block_write = ssb_ssb_block_write, > +#endif > + .device_is_enabled = ssb_device_is_enabled_ai, > + .device_enable = ssb_device_enable_ai, > + .device_disable = ssb_device_disable_ai, > + .admatch_base = ssb_admatch_base_ai, > + .admatch_size = ssb_admatch_size_ai, > + .irqflag = ssb_irqflag_ai, > + .core_ctl_flags = ssb_core_ctl_flags_ai, > + .core_state_flags = ssb_core_state_flags_ai, > +}; > + > +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; > + > + /* 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; > +} > + > +int ssb_bus_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; > + > + bus->ops = &ssb_ops_ai; > + > + 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) > + /* don't record bridges */ > + continue; > + 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; > + } > + > + dev->coresba = addrl; > + dev->coresba_size = sizel; > + > + /* Try to get one more Slave Address Descriptor in port 0 */ > + asd = get_erom_ent(bus, &eromptr, SSB_EROM_VALID, > + SSB_EROM_VALID) & (SSB_EROM_ASD_SP_MASK | > + SSB_EROM_ASD_ST_MASK | > + SSB_EROM_TAG); > + eromptr--; > + if (asd == SSB_EROM_ASD) { > + asd = get_adress_space_descriptor(bus, &eromptr, > + SSB_EROM_ASD_ST_SLAVE, > + &addrl, &sizel); > + if (sizel != SSB_CORE_SIZE) { > + ssb_printk(KERN_ERR PFX > + "Malformed or unsupported ai " > + "address space descriptor for " > + "core %d:\n\texpected 0x%x size, " > + "got 0x%x size\n", > + dev_i, SSB_CORE_SIZE, sizel); > + return -EIO; > + } > + dev->coresba2 = addrl; > + dev->coresba2_size = sizel; > + } > + > + 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; > +} > --- linux-next-20110203.orig/drivers/ssb/ssb_ai.h 1970-01-01 03:00:00.000000000 +0300 > +++ linux-next-20110203/drivers/ssb/ssb_ai.h 2011-02-08 21:01:34.000000000 +0200 > @@ -0,0 +1,61 @@ > +#ifndef LINUX_SSB_AI_H_ > +#define LINUX_SSB_AI_H_ > + > +#define SSB_AI_BASE 0x18100000 /* base for AI registers */ > + > +/* EROM parsing defines */ > +#define SSB_EROM_VALID 1 > +#define SSB_EROM_END 0x0E > +#define SSB_EROM_TAG 0x0E > + > +/* Adress Space Descriptor */ > +#define SSB_EROM_ASD 0x4 > +#define SSB_EROM_ASD_SP_MASK 0x00000F00 > +#define SSB_EROM_ASD_SP_SHIFT 8 > +#define SSB_EROM_ASD_ST_MASK 0x000000c0 > +#define SSB_EROM_ASD_ST_SLAVE 0x00000000 > +#define SSB_EROM_ASD_ST_BRIDGE 0x00000040 > +#define SSB_EROM_ASD_ST_MWRAP 0x000000C0 > +#define SSB_EROM_ASD_ST_SWRAP 0x00000080 > +#define SSB_EROM_ASD_ADDR_MASK 0xFFFFF000 > +#define SSB_EROM_ASD_AG32 0x00000008 > +#define SSB_EROM_ASD_SZ_MASK 0x00000030 > +#define SSB_EROM_ASD_SZ_SZD 0x00000030 > +#define SSB_EROM_ASD_SZ_SHIFT 4 > +#define SSB_EROM_ASD_SZ_BASE 0x00001000 > +#define SSB_EROM_CI 0 > +#define SSB_EROM_CIA_CID_MASK 0x000FFF00 > +#define SSB_EROM_CIA_CID_SHIFT 8 > +#define SSB_EROM_CIA_MFG_MASK 0xFFF00000 > +#define SSB_EROM_CIA_MFG_SHIFT 20 > +#define SSB_EROM_CIB_REV_MASK 0xFF000000 > +#define SSB_EROM_CIB_REV_SHIFT 24 > +#define SSB_EROM_CIB_NMW_MASK 0x0007C000 > +#define SSB_EROM_CIB_NMW_SHIFT 14 > +#define SSB_EROM_CIB_NSW_MASK 0x00F80000 > +#define SSB_EROM_CIB_NSW_SHIFT 19 > +#define SSB_EROM_CIB_NSP_MASK 0x00003E00 > +#define SSB_EROM_CIB_NSP_SHIFT 9 > + > +/* Adress Space Descriptor macro defs */ > +#define SSB_EROM_CIA_CID(cia) (((cia) & SSB_EROM_CIA_CID_MASK) >> \ > + SSB_EROM_CIA_CID_SHIFT) > +#define SSB_EROM_CIA_MFG(cia) (((cia) & SSB_EROM_CIA_MFG_MASK) >> \ > + SSB_EROM_CIA_MFG_SHIFT) > +#define SSB_EROM_CIB_REV(cib) (((cib) & SSB_EROM_CIB_REV_MASK) >> \ > + SSB_EROM_CIB_REV_SHIFT) > +#define SSB_EROM_CIB_NMW(cib) (((cib) & SSB_EROM_CIB_NMW_MASK) >> \ > + SSB_EROM_CIB_NMW_SHIFT) > +#define SSB_EROM_CIB_NSW(cib) (((cib) & SSB_EROM_CIB_NSW_MASK) >> \ > + SSB_EROM_CIB_NSW_SHIFT) > +#define SSB_EROM_CIB_NSP(cib) (((cib) & SSB_EROM_CIB_NSP_MASK) >> \ > + SSB_EROM_CIB_NSP_SHIFT) > + > +/* AI config space registers */ > +#define SSB_AI_oobselouta30 0x100 > +#define SSB_AI_IOCTL 0x408 /* maybe 0x40C for big endian */ > +#define SSB_AI_IOSTAT 0x500 > +#define SSB_AI_RESETCTL 0x800 /* maybe 0x804 for big endian */ > +#define SSB_AI_RESETCTL_RESET 1 > + > +#endif /* LINUX_SSB_AI_H_ */ > --- linux-next-20110203.orig/drivers/ssb/ssb_private.h 2011-02-08 16:14:57.000000000 +0200 > +++ linux-next-20110203/drivers/ssb/ssb_private.h 2011-02-08 21:01:34.000000000 +0200 > @@ -236,4 +236,13 @@ static inline int ssb_bus_scan_sb(struct > } > #endif /* CONFIG_SSB_BUS_SB */ > > +#ifdef CONFIG_SSB_BUS_AI > +extern int ssb_bus_scan_ai(struct ssb_bus *bus); > +#else /* CONFIG_SSB_BUS_AI */ > +static inline int ssb_bus_scan_ai(struct ssb_bus *bus) > +{ > + return -ENODEV; > +} > +#endif /* CONFIG_SSB_BUS_AI */ > + > #endif /* LINUX_SSB_PRIVATE_H_ */ > --- linux-next-20110203.orig/include/linux/ssb/ssb_driver_chipcommon.h 2011-02-08 13:49:32.000000000 +0200 > +++ linux-next-20110203/include/linux/ssb/ssb_driver_chipcommon.h 2011-02-08 21:01:34.000000000 +0200 > @@ -19,6 +19,7 @@ > #define SSB_CHIPCO_TYPE_MASK 0xF0000000 > #define SSB_CHIPCO_TYPE_SHIFT 28 > #define SSB_CHIPCO_TYPE_SB 0 > +#define SSB_CHIPCO_TYPE_AI 0x10000000 > #define SSB_CHIPCO_IDMASK 0x0000FFFF > #define SSB_CHIPCO_REVMASK 0x000F0000 > #define SSB_CHIPCO_REVSHIFT 16 > @@ -173,6 +174,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 0x00FC /* erom for AI socs */ > #define SSB_CHIPCO_PCMCIA_CFG 0x0100 > #define SSB_CHIPCO_PCMCIA_MEMWAIT 0x0104 > #define SSB_CHIPCO_PCMCIA_ATTRWAIT 0x0108 > @@ -584,6 +586,7 @@ struct ssb_chipcommon_pmu { > /* Chipcommon implementation type */ > enum ssb_chipco_chiptype { > SSB_CHIPCO_SB = SSB_CHIPCO_TYPE(SSB_CHIPCO_TYPE_SB), /* SB-style bus */ > + SSB_CHIPCO_AI = SSB_CHIPCO_TYPE(SSB_CHIPCO_TYPE_AI), /* AI-style bus */ > }; > > struct ssb_chipcommon { > --- linux-next-20110203.orig/include/linux/ssb/ssb.h 2011-02-08 18:33:58.000000000 +0200 > +++ linux-next-20110203/include/linux/ssb/ssb.h 2011-02-08 21:01:34.000000000 +0200 > @@ -168,9 +168,11 @@ struct ssb_bus_ops { > #define SSB_DEV_MIPS_74K 0x82C > #define SSB_DEV_DDR_CTRLR 0x82E > #define SSB_DEV_I2S 0x834 > +#define SSB_DEV_DEFAULT 0xFFF > > /* Vendor-ID values */ > #define SSB_VENDOR_BROADCOM 0x4243 > +#define SSB_VENDOR_ARM 0x043B > > /* Some kernel subsystems poke with dev->drvdata, so we must use the > * following ugly workaround to get from struct device to struct ssb_device */ > @@ -192,6 +194,13 @@ struct ssb_device { > u8 core_index; > unsigned int irq; > > +#ifdef CONFIG_SSB_BUS_AI > + /* backplane address and size for core */ > + u32 coresba, coresba_size; > + /* address and size of core second register set (usbh20) */ > + u32 coresba2, coresba2_size; > +#endif > + > /* Internal-only stuff follows. */ > void *drvdata; /* Per-device data */ > void *devtypedata; /* Per-devicetype (eg 802.11) data */ > @@ -283,6 +292,9 @@ enum ssb_bustype { > struct ssb_bus { > /* The MMIO area. */ > void __iomem *mmio; > +#ifdef CONFIG_SSB_BUS_AI > + void __iomem *ai_mmio; > +#endif > > const struct ssb_bus_ops *ops; > > > After I used wiggle to fix this patch, the resulting stuff would not compile. The messages are CC [M] drivers/ssb/scan.o drivers/ssb/scan.c: In function ?ssb_bus_detect?: drivers/ssb/scan.c:379:6: error: ?cpu_data? undeclared (first use in this function) drivers/ssb/scan.c:379:6: note: each undeclared identifier is reported only once for each function it appears in drivers/ssb/scan.c:379:29: error: ?CPU_74K? undeclared (first use in this function) make[1]: *** [drivers/ssb/scan.o] Error 1 make: *** [drivers/ssb/] Error 2 Larry