From: George Kashperko <george@znau.edu.ua>
To: linux-wireless <linux-wireless@vger.kernel.org>
Subject: Re: [RFC] AI support (13/14 ssb add AI support)
Date: Fri, 18 Feb 2011 00:31:22 +0200 [thread overview]
Message-ID: <1297981882.23381.38.camel@dev.znau.edu.ua> (raw)
In-Reply-To: <1297980093.13554.5.camel@maggie>
From: George Kashperko <george@znau.edu.ua>
Add support for AI-style bus.
Signed-off-by: George Kashperko <george@znau.edu.ua>
---
drivers/ssb/Kconfig | 11
drivers/ssb/Makefile | 1
drivers/ssb/main.c | 2
drivers/ssb/scan.c | 47 +-
drivers/ssb/ssb_ai.c | 407 ++++++++++++++++++++
drivers/ssb/ssb_ai.h | 79 +++
drivers/ssb/ssb_private.h | 6
include/linux/ssb/ssb.h | 44 ++
include/linux/ssb/ssb_driver_chipcommon.h | 3
include/linux/ssb/ssb_regs.h | 1
10 files changed, 593 insertions(+), 8 deletions(-)
--- linux-wireless-testing.orig/drivers/ssb/Kconfig 2011-02-17 15:56:58.000000000 +0200
+++ linux-wireless-testing/drivers/ssb/Kconfig 2011-02-17 15:57:14.000000000 +0200
@@ -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
+ Broadcom AI-style bus
+
# Common SPROM support routines
config SSB_SPROM
bool
--- linux-wireless-testing.orig/drivers/ssb/main.c 2011-02-17 15:56:58.000000000 +0200
+++ linux-wireless-testing/drivers/ssb/main.c 2011-02-17 15:57:14.000000000 +0200
@@ -855,6 +855,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-wireless-testing.orig/drivers/ssb/Makefile 2011-02-17 15:56:58.000000000 +0200
+++ linux-wireless-testing/drivers/ssb/Makefile 2011-02-17 15:57:14.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-wireless-testing.orig/drivers/ssb/scan.c 2011-02-17 15:57:09.000000000 +0200
+++ linux-wireless-testing/drivers/ssb/scan.c 2011-02-17 15:57:14.000000000 +0200
@@ -326,19 +326,48 @@ int ssb_bus_check_core(struct ssb_device
return 0;
}
+static inline bool ssb_can_read_idhi(void)
+{
+#ifdef CONFIG_MIPS
+ return cpu_data[0].cputype != CPU_74K;
+#else
+ return true;
+#endif
+}
+
/* 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 (ssb_can_read_idhi()) {
+ 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);
@@ -375,7 +404,8 @@ static int ssb_bus_detect(struct ssb_bus
}
bus->chipco.chiptype = chiptype;
- return chiptype == SSB_CHIPCO_SB ? 0 : -ENODEV;
+ return (chiptype == SSB_CHIPCO_SB ||
+ chiptype == SSB_CHIPCO_AI) ? 0 : -ENODEV;
}
int ssb_bus_scan(struct ssb_bus *bus, unsigned long baseaddr)
@@ -416,6 +446,9 @@ int ssb_bus_scan(struct ssb_bus *bus, un
case SSB_CHIPCO_SB:
err = ssb_bus_scan_sb(bus, baseaddr);
break;
+ case SSB_CHIPCO_AI:
+ err = ssb_bus_scan_ai(bus, baseaddr);
+ break;
default:
SSB_WARN_ON(1);
err = -ENODEV;
--- linux-wireless-testing.orig/drivers/ssb/ssb_ai.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-wireless-testing/drivers/ssb/ssb_ai.c 2011-02-17 15:57:14.000000000 +0200
@@ -0,0 +1,407 @@
+/*
+ * Sonics Silicon Backplane
+ * AI Specific Subsystem core
+ *
+ * Copyright 2011, George Kashperko <george@znau.edu.ua>
+ * Copyright 2010, Bernhard Loos <bernhardloos@googlemail.com>
+ * Copyright (C) 2006 Broadcom Corporation.
+ *
+ * Licensed under the GNU/GPL. See COPYING for details.
+ */
+
+#include <linux/delay.h>
+#include <linux/ssb/ssb.h>
+#include <linux/ssb/ssb_regs.h>
+
+#include "ssb_private.h"
+#include "ssb_ai.h"
+
+
+static inline u32 ssb_airead32(struct ssb_device *dev, u16 offset)
+{
+ return dev->ai.ops->read32(dev, offset);
+}
+
+static inline void ssb_aiwrite32(struct ssb_device *dev, u16 offset, u32 value)
+{
+ dev->ai.ops->write32(dev, offset, value);
+}
+
+static u32 ssb_ssb_airead32(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 void ssb_ssb_aiwrite32(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);
+}
+
+struct ssb_bus_aiops ssb_ssb_aiops = {
+ .read32 = ssb_ssb_airead32,
+ .write32 = ssb_ssb_aiwrite32,
+};
+
+/* 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 u32 ssb_core_ctl_flags_ai(struct ssb_device *dev, u32 mask, u32 val)
+{
+ if (ssb_bcm47162a0_quirk(dev)) {
+ ssb_printk(KERN_ERR PFX "%s: Accessing MIPS DMP register "
+ "(IOCTL) on 47162a0", __func__);
+ return 0;
+ }
+
+ SSB_WARN_ON((~mask | val) & 0xFFFF0000);
+
+ if (~mask || val) {
+ u32 tmp = (ssb_airead32(dev, SSB_AI_IOCTL) & mask) | val;
+ ssb_aiwrite32(dev, SSB_AI_IOCTL, tmp);
+ }
+
+ return ssb_airead32(dev, SSB_AI_IOCTL);
+}
+
+static u32 ssb_core_state_flags_ai(struct ssb_device *dev)
+{
+ if (ssb_bcm47162a0_quirk(dev)) {
+ ssb_printk(KERN_ERR PFX "%s: Accessing MIPS DMP register "
+ "(IOSTAT) on 47162a0", __func__);
+ return 0;
+ }
+ return ssb_airead32(dev, SSB_AI_IOSTAT);
+}
+
+#ifdef CONFIG_SSB_DRIVER_MIPS
+/* return -1 if no irq is supported */
+static u32 ssb_irqflag_ai(struct ssb_device *dev)
+{
+ u32 flag;
+
+ if (ssb_bcm47162a0_quirk(dev))
+ return dev->core_index;
+
+ flag = ssb_airead32(dev, SSB_AI_oobselouta30) & 0x1F;
+
+ if (flag && flag != 0x1F)
+ return flag;
+ else
+ /* not irq supported */
+ return -1;
+}
+#endif /* CONFIG_SSB_DRIVER_MIPS */
+
+static int ssb_device_is_enabled_ai(struct ssb_device *dev)
+{
+ return (ssb_airead32(dev, SSB_AI_RESETCTL) &
+ SSB_AI_RESETCTL_RESET) == 0;
+}
+
+static void ssb_aiioctl_write(struct ssb_device *dev, u32 flags)
+{
+ u32 dummy;
+ ssb_aiwrite32(dev, SSB_AI_IOCTL, flags);
+ dummy = ssb_airead32(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_airead32(dev, SSB_AI_RESETCTL) & SSB_AI_RESETCTL_RESET)
+ return;
+ ssb_aiioctl_write(dev, core_specific_flags);
+ udelay(9);
+ ssb_aiwrite32(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_aiioctl_write(dev, core_specific_flags | SSB_CORECTL_FGC |
+ SSB_CORECTL_CLOCK);
+ ssb_aiwrite32(dev, SSB_AI_RESETCTL, 0);
+ udelay(1);
+
+ ssb_aiioctl_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->ai.core[0].base;
+ case SSB_ADMATCH1:
+ return dev->ai.core[1].base;
+ 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->ai.core[0].size;
+ case SSB_ADMATCH1:
+ return dev->ai.core[1].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;
+ }
+}
+
+const struct ssb_bus_helpers ssb_helpers_ai = {
+ .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,
+ .core_ctl_flags = ssb_core_ctl_flags_ai,
+ .core_state_flags = ssb_core_state_flags_ai,
+};
+
+void ssb_iounmap_ai(struct ssb_bus *bus)
+{
+ switch (bus->bustype) {
+ case SSB_BUSTYPE_SSB:
+ iounmap(bus->mmio);
+ iounmap(bus->ai.mmio);
+ break;
+ default:
+ break;
+ }
+ bus->mmio = NULL;
+ bus->ai.mmio = NULL;
+ bus->mapped_device = NULL;
+ bus->ai.mapped_device = NULL;
+}
+
+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, unsigned long baseaddr)
+{
+ int dev_i = 0, nr_80211_cores = 0;
+ struct ssb_device *dev;
+ u32 erombase;
+ u32 __iomem *eromptr, *eromend;
+
+ erombase = scan_read32(bus, 0, SSB_CHIPCO_EROM);
+
+ switch (bus->bustype) {
+ case SSB_BUSTYPE_SSB:
+ bus->ai.ops = &ssb_ssb_aiops;
+ eromptr = ioremap(erombase, SSB_CORE_SIZE);
+ if (!eromptr)
+ return -ENOMEM;
+ break;
+ default:
+ return -ENODEV;
+ }
+
+ eromend = eromptr + SSB_CORE_SIZE / sizeof(u32);
+
+#ifdef CONFIG_SSB_DRIVER_MIPS
+ bus->mipscore.irqflag = ssb_irqflag_ai;
+#endif /* CONFIG_SSB_DRIVER_MIPS */
+
+ 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->helpers = &ssb_helpers_ai;
+ dev->ops = bus->ops;
+ dev->ai.ops = bus->ai.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->ai.core[0].base = addrl;
+ dev->ai.core[0].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->ai.core[1].base = addrl;
+ dev->ai.core[1].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");
+
+ if (bus->bustype == SSB_BUSTYPE_SSB && dev_i) {
+ /* remap as we got final num of cores */
+ bus->ai.mmio = ioremap(SSB_AI_BASE, SSB_CORE_SIZE * dev_i);
+ if (!bus->ai.mmio)
+ return -ENOMEM;
+ }
+
+ return 0;
+}
--- linux-wireless-testing.orig/drivers/ssb/ssb_ai.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-wireless-testing/drivers/ssb/ssb_ai.h 2011-02-17 15:57:14.000000000 +0200
@@ -0,0 +1,79 @@
+#ifndef LINUX_SSB_AI_H_
+#define LINUX_SSB_AI_H_
+
+#ifdef CONFIG_SSB_BUS_AI
+
+#define SSB_AI_BASE 0x18100000U /* 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
+
+extern void ssb_iounmap_ai(struct ssb_bus *bus);
+extern int ssb_bus_scan_ai(struct ssb_bus *bus, unsigned long baseaddr);
+
+#else /* CONFIG_SSB_BUS_AI */
+
+static inline void ssb_iounmap_ai(struct ssb_bus *bus)
+{
+}
+
+static inline int ssb_bus_scan_ai(struct ssb_bus *bus, unsigned long baseaddr)
+{
+ return -ENODEV;
+}
+
+#endif /* CONFIG_SSB_BUS_AI */
+
+#endif /* !LINUX_SSB_AI_H_ */
--- linux-wireless-testing.orig/drivers/ssb/ssb_private.h 2011-02-17 15:56:58.000000000 +0200
+++ linux-wireless-testing/drivers/ssb/ssb_private.h 2011-02-17 15:57:14.000000000 +0200
@@ -4,6 +4,7 @@
#include <linux/ssb/ssb.h>
#include <linux/types.h>
#include "ssb_sb.h"
+#include "ssb_ai.h"
#define PFX "ssb: "
@@ -168,7 +169,10 @@ extern int ssb_bus_check_core(struct ssb
extern u32 scan_read32(struct ssb_bus *bus, u8 current_coreidx, u16 offset);
static inline void ssb_iounmap(struct ssb_bus *bus)
{
- ssb_iounmap_sb(bus);
+ if (bus->chipco.chiptype == SSB_CHIPCO_AI)
+ ssb_iounmap_ai(bus);
+ else
+ ssb_iounmap_sb(bus);
}
--- linux-wireless-testing.orig/include/linux/ssb/ssb_driver_chipcommon.h 2011-02-17 15:51:11.000000000 +0200
+++ linux-wireless-testing/include/linux/ssb/ssb_driver_chipcommon.h 2011-02-17 15:57:14.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-wireless-testing.orig/include/linux/ssb/ssb.h 2011-02-17 15:57:09.000000000 +0200
+++ linux-wireless-testing/include/linux/ssb/ssb.h 2011-02-17 15:57:14.000000000 +0200
@@ -104,6 +104,46 @@ struct ssb_boardinfo {
struct ssb_device;
+#ifdef CONFIG_SSB_BUS_AI
+/* max no of AI addrspaces */
+#define SSB_AI_MAX_ADDRSPACES 2
+
+struct ssb_bus_aiops {
+ u32 (*read32)(struct ssb_device *dev, u16 offset);
+ void (*write32)(struct ssb_device *dev, u16 offset, u32 value);
+};
+
+struct ssb_aiaddrspace {
+ u32 base;
+ u32 size;
+};
+
+/* AI-style bus device-specific data */
+struct ssb_aidevice {
+ /** Internal stuff, don't use directly **/
+ struct ssb_bus_aiops *ops;
+ /* device cores */
+ struct ssb_aiaddrspace core[SSB_AI_MAX_ADDRSPACES];
+};
+
+/* AI-style bus-specific data */
+struct ssb_aibus {
+ /** Internal stuff, don't use directly **/
+ struct ssb_bus_aiops *ops;
+ /* core wrapper IO area */
+ void __iomem *mmio;
+ /* core, which wrapper is currently mapped into the MMIO window */
+ struct ssb_device *mapped_device;
+};
+#else /* CONFIG_SSB_BUS_AI */
+struct ssb_aidevice {
+};
+
+struct ssb_aibus {
+};
+#endif /* CONFIG_SSB_BUS_AI */
+
+
/* Lowlevel read/write operations on the device MMIO.
* Internal, don't use that outside of ssb. */
struct ssb_bus_ops {
@@ -170,9 +210,11 @@ struct ssb_bus_helpers {
#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 */
@@ -198,6 +240,7 @@ struct ssb_device {
/* Internal-only stuff follows. */
void *drvdata; /* Per-device data */
void *devtypedata; /* Per-devicetype (eg 802.11) data */
+ struct ssb_aidevice ai; /* AI-specific device data */
};
/* Go from struct device to struct ssb_device. */
@@ -364,6 +407,7 @@ struct ssb_bus {
/* Internal-only stuff follows. Do not touch. */
struct list_head list;
+ struct ssb_aibus ai; /* AI-specific bus data */
#ifdef CONFIG_SSB_DEBUG
/* Is the bus already powered up? */
bool powered_up;
--- linux-wireless-testing.orig/include/linux/ssb/ssb_regs.h 2011-02-17 15:40:20.000000000 +0200
+++ linux-wireless-testing/include/linux/ssb/ssb_regs.h 2011-02-17 15:57:14.000000000 +0200
@@ -54,6 +54,7 @@
#define SSB_GPIO_HWRAD 0x20 /* PCI config space GPIO 13 for hw radio disable */
#define SSB_GPIO_XTAL 0x40 /* PCI config space GPIO 14 for Xtal powerup */
#define SSB_GPIO_PLL 0x80 /* PCI config space GPIO 15 for PLL powerdown */
+#define SSB_BAR0_WIN2 0xAC /* backplane addres space accessed by second 4KB of BAR0 */
#define SSB_BAR0_MAX_RETRIES 50
next prev parent reply other threads:[~2011-02-17 22:39 UTC|newest]
Thread overview: 38+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-02-17 15:58 [RFC] AI support George Kashperko
2011-02-17 22:01 ` Michael Büsch
2011-02-17 22:06 ` [RFC] AI support (1/14 ssb admatch redefine) George Kashperko
2011-02-17 22:08 ` [RFC] AI support (2/14 ssb helpers) George Kashperko
2011-02-18 22:29 ` Michael Büsch
2011-02-18 23:15 ` George Kashperko
2011-02-18 23:29 ` Michael Büsch
2011-02-18 23:27 ` George Kashperko
2011-02-17 22:10 ` [RFC] AI support (3/14 ssb irqflag mips core op) George Kashperko
2011-02-17 22:12 ` [RFC] AI support (4/14 ssb mips core irqflag treatment) George Kashperko
2011-02-17 22:14 ` [RFC] AI support (5/14 ssb core control and state helpers) George Kashperko
2011-02-17 22:16 ` [RFC] AI support (6/14 ssb propagate core control and state helpers usage) George Kashperko
2011-02-17 22:18 ` [RFC] AI support (7/14 ssb bus_check_core routine) George Kashperko
2011-02-17 22:20 ` [RFC] AI support (8/14 ssb ssb_bus_detect routine) George Kashperko
2011-02-18 22:35 ` Michael Büsch
2011-02-17 22:23 ` [RFC] AI support (9/14 ssb SB-specific bus scan routine) George Kashperko
2011-02-17 22:25 ` [RFC] AI support (10/14 ssb bus implementation-specific io unmap) George Kashperko
2011-02-17 22:27 ` [RFC] AI support (11/14 ssb separate SB-specific code) George Kashperko
2011-02-17 22:29 ` [RFC] AI support (12/14 ssb mips74k core defs) George Kashperko
2011-02-17 22:31 ` George Kashperko [this message]
2011-02-18 22:45 ` [RFC] AI support (13/14 ssb add AI support) Michael Büsch
2011-02-18 23:07 ` George Kashperko
2011-02-18 23:27 ` Michael Büsch
2011-02-18 23:42 ` George Kashperko
2011-02-18 23:54 ` Michael Büsch
2011-02-18 23:51 ` George Kashperko
2011-02-18 23:46 ` Larry Finger
2011-02-18 23:47 ` George Kashperko
2011-02-19 0:06 ` Larry Finger
2011-02-19 0:08 ` George Kashperko
2011-02-19 0:22 ` Larry Finger
2011-02-17 22:35 ` [RFC] AI support (14/14 ssb AI on pci host (untested)) George Kashperko
2011-02-18 2:43 ` [RFC] AI support Henry Ptasinski
2011-02-18 7:39 ` George Kashperko
2011-02-18 11:53 ` Michael Büsch
2011-02-18 12:39 ` George Kashperko
2011-02-18 22:21 ` Michael Büsch
2011-02-18 22:52 ` George Kashperko
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1297981882.23381.38.camel@dev.znau.edu.ua \
--to=george@znau.edu.ua \
--cc=linux-wireless@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).