All of lore.kernel.org
 help / color / mirror / Atom feed
From: Michael Buesch <mb@bu3sch.de>
To: netdev@vger.kernel.org
Cc: bcm43xx-dev@lists.berlios.de, zambrano@broadcom.com
Subject: [patch RFC 1/3] add Sonics Silicon Backplane module
Date: Tue, 15 Aug 2006 00:15:37 +0200	[thread overview]
Message-ID: <200608150015.38510.mb@bu3sch.de> (raw)
In-Reply-To: <200608150014.19661.mb@bu3sch.de>

Signed-off-by: Michael Buesch <mb@bu3sch.de>

Index: wireless-dev/drivers/misc/Kconfig
===================================================================
--- wireless-dev.orig/drivers/misc/Kconfig	2006-08-14 15:31:50.000000000 +0200
+++ wireless-dev/drivers/misc/Kconfig	2006-08-14 22:02:07.000000000 +0200
@@ -28,5 +28,16 @@
 
 	  If unsure, say N.
 
+config SONICS_SILICON_BACKPLANE
+	tristate "Sonics Silicon Backplane support"
+	depends on PCI && EXPERIMENTAL
+	default m
+	---help---
+	  The Sonics Silicon Backplane is used in some chips such
+	  as the Broadcom 43xx and 44xx series.
+	  The Backplane ties several chip-cores together.
+
+	  If unsure, say M.
+
 endmenu
 
Index: wireless-dev/drivers/misc/Makefile
===================================================================
--- wireless-dev.orig/drivers/misc/Makefile	2006-08-14 15:31:50.000000000 +0200
+++ wireless-dev/drivers/misc/Makefile	2006-08-14 22:02:07.000000000 +0200
@@ -3,5 +3,6 @@
 #
 obj- := misc.o	# Dummy rule to force built-in.o to be made
 
-obj-$(CONFIG_IBM_ASM)	+= ibmasm/
-obj-$(CONFIG_HDPU_FEATURES)	+= hdpuftrs/
+obj-$(CONFIG_IBM_ASM)			+= ibmasm/
+obj-$(CONFIG_HDPU_FEATURES)		+= hdpuftrs/
+obj-$(CONFIG_SONICS_SILICON_BACKPLANE)	+= ssb.o
Index: wireless-dev/drivers/misc/ssb.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ wireless-dev/drivers/misc/ssb.c	2006-08-14 23:19:34.000000000 +0200
@@ -0,0 +1,502 @@
+/*
+ * Sonics Silicon Backplane backend.
+ *
+ * Copyright (C) 2005-2006 Michael Buesch <mb@bu3sch.de>
+ * Copyright (C) 2005 Martin Langer <martin-langer@gmx.de>
+ * Copyright (C) 2005 Stefano Brivio <st3@riseup.net>
+ * Copyright (C) 2005 Danny van Dyk <kugelfang@gentoo.org>
+ * Copyright (C) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
+ *
+ * Derived from the Broadcom 4400 device driver.
+ * Copyright (C) 2002 David S. Miller (davem@redhat.com)
+ * Fixed by Pekka Pietikainen (pp@ee.oulu.fi)
+ * Copyright (C) 2006 Broadcom Corporation.
+ *
+ * Licensed under the GNU/GPL. See COPYING for details.
+ */
+
+#include <linux/ssb.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+
+#define SSB_DEBUG	1
+#define PFX		"ssb: "
+
+#if SSB_DEBUG
+# define dprintk(f, x...)	do { printk(f ,##x); } while (0)
+#else
+# define dprintk(f, x...)	do { /* nothing */ } while (0)
+#endif
+
+static inline int ssb_pci_read_config32(struct ssb *ssb, int offset,
+					u32 *value)
+{
+	return pci_read_config_dword(ssb->pci_dev, offset, value);
+}
+
+static inline int ssb_pci_read_config16(struct ssb *ssb, int offset,
+					u16 *value)
+{
+	return pci_read_config_word(ssb->pci_dev, offset, value);
+}
+
+static inline int ssb_pci_write_config32(struct ssb *ssb, int offset,
+					 u32 value)
+{
+	return pci_write_config_dword(ssb->pci_dev, offset, value);
+}
+
+static inline u32 ssb_read32(struct ssb *ssb, u16 offset)
+{
+	return ioread32(ssb->mmio + offset + ssb_core_offset(ssb));
+}
+
+static inline void ssb_write32(struct ssb *ssb, u16 offset,
+			       u32 value)
+{
+	iowrite32(value, ssb->mmio + offset + ssb_core_offset(ssb));
+}
+
+
+struct ssb * ssb_alloc(struct pci_dev *pci_dev,
+		       void __iomem *mmio)
+{
+	struct ssb *ssb;
+
+	ssb = kzalloc(sizeof(*ssb), GFP_KERNEL);
+	if (!ssb)
+		return NULL;
+
+	ssb->pci_dev = pci_dev;
+	ssb->mmio = mmio;
+
+	return ssb;
+}
+EXPORT_SYMBOL(ssb_alloc);
+
+void ssb_free(struct ssb *ssb)
+{
+	kfree(ssb->cores);
+	kfree(ssb);
+}
+EXPORT_SYMBOL(ssb_free);
+
+static int do_switch_core(struct ssb *ssb, u8 coreidx)
+{
+	int err;
+	int attempts = 0;
+	u32 cur_core;
+
+	while (1) {
+		err = ssb_pci_write_config32(ssb, SSB_BAR0_WIN,
+					     (coreidx * 0x1000) + 0x18000000);
+		if (unlikely(err))
+			goto error;
+		err = ssb_pci_read_config32(ssb, SSB_BAR0_WIN,
+					    &cur_core);
+		if (unlikely(err))
+			goto error;
+		cur_core = (cur_core - 0x18000000) / 0x1000;
+		if (cur_core == coreidx)
+			break;
+
+		if (unlikely(attempts++ > SSB_BAR0_MAX_RETRIES))
+			goto error;
+		udelay(10);
+	}
+#ifdef CONFIG_BCM947XX
+	ssb->current_core_offset = 0;
+	if (ssb->pci_dev->bus->number == 0)
+		ssb->current_core_offset = 0x1000 * coreidx;
+#endif /* CONFIG_BCM947XX */
+
+	return 0;
+error:
+	printk(KERN_ERR PFX "Failed to switch to core %u\n", coreidx);
+	return -ENODEV;
+}
+
+int ssb_switch_core(struct ssb *ssb,
+		    struct ssb_core *new_core)
+{
+	int err;
+
+	if (unlikely(!new_core))
+		return -EINVAL;
+	if (ssb->current_core == new_core)
+		return 0;
+	err = do_switch_core(ssb, new_core->index);
+	if (likely(!err))
+		ssb->current_core = new_core;
+
+	return err;
+}
+EXPORT_SYMBOL(ssb_switch_core);
+
+int ssb_probe_cores(struct ssb *ssb,
+		    u16 chipid_fallback,
+		    const struct ssb_nrcores_elem *nrcores_fallback,
+		    size_t nrcores_fb_size)
+{
+	struct ssb_core *core;
+	int err = -ENODEV;
+	u32 idhi;
+	u32 cc, rev;
+	u32 tmp;
+	int i;
+
+	WARN_ON(ssb->cores);
+
+	err = do_switch_core(ssb, 0);
+	if (err)
+		goto error;
+
+	idhi = ssb_read32(ssb, SSB_IDHIGH);
+	cc = (idhi & SSB_IDHIGH_CC_MASK) >> SSB_IDHIGH_CC_SHIFT;
+	rev = (idhi & SSB_IDHIGH_RC_MASK);
+
+	ssb->chipcommon_capabilities = 0;
+	ssb->nr_cores = 0;
+	if (cc == SSB_CC_CHIPCOMMON) {
+		tmp = ssb_read32(ssb, SSB_CHIPCOMMON_CHIPID);
+
+		ssb->chip_id = (tmp & SSB_CHIPCOMMON_IDMASK);
+		ssb->chip_rev = (tmp & SSB_CHIPCOMMON_REVMASK) >>
+				SSB_CHIPCOMMON_REVSHIFT;
+		ssb->chip_package = (tmp & SSB_CHIPCOMMON_PACKMASK) >>
+				    SSB_CHIPCOMMON_PACKSHIFT;
+		if (rev >= 4) {
+			ssb->nr_cores = (tmp & SSB_CHIPCOMMON_NRCORESMASK) >>
+					SSB_CHIPCOMMON_NRCORESSHIFT;
+		}
+		tmp = ssb_read32(ssb, SSB_CHIPCOMMON_CAPABILITIES);
+		ssb->chipcommon_capabilities = tmp;
+	} else {
+		u16 revtmp;
+
+		if (chipid_fallback == 0) {
+			printk(KERN_ERR PFX "No ChipCommon rev >= 4 present and "
+					    "chipid_fallback == 0\n");
+			goto error;
+		}
+		ssb->chip_id = chipid_fallback;
+		err = ssb_pci_read_config16(ssb, PCI_REVISION_ID, &revtmp);
+		if (err)
+			goto error;
+		ssb->chip_rev = revtmp;
+		ssb->chip_package = 0;
+	}
+	if (!ssb->nr_cores) {
+		const struct ssb_nrcores_elem *elem;
+
+		/* Search the fallback array. */
+		if (!nrcores_fallback) {
+			printk(KERN_ERR PFX "Could not read number of cores from "
+					    "ChipCommon and no nrcores_fallback "
+					    "available\n");
+			goto error;
+		}
+		for (i = 0; i < nrcores_fb_size; i++) {
+			elem = &(nrcores_fallback[i]);
+			if (elem->chip_id_key == ssb->chip_id) {
+				ssb->nr_cores = elem->nr_cores_value;
+				break;
+			}
+		}
+	}
+	if (!ssb->nr_cores) {
+		printk(KERN_ERR PFX "Could not determine number of cores.\n");
+		goto error;
+	}
+
+	ssb->cores = kcalloc(ssb->nr_cores, sizeof(struct ssb_core),
+			     GFP_KERNEL);
+	if (!ssb->cores)
+		goto error;
+
+	for (i = 0; i < ssb->nr_cores; i++) {
+		err == do_switch_core(ssb, i);
+		if (err)
+			goto error;
+		core = &(ssb->cores[i]);
+
+		idhi = ssb_read32(ssb, SSB_IDHIGH);
+		core->cc = (idhi & SSB_IDHIGH_CC_MASK) >> SSB_IDHIGH_CC_SHIFT;
+		core->rev = (idhi & SSB_IDHIGH_RC_MASK);
+		core->vendor = (idhi & SSB_IDHIGH_VC_MASK) >> SSB_IDHIGH_VC_SHIFT;
+		core->index = i;
+
+		dprintk(KERN_DEBUG PFX "Core %d found: "
+				       "cc %04X, rev %02X, vendor %04X\n",
+			i, core->cc, core->rev, core->vendor);
+	}
+
+	return 0;
+error:
+	printk(KERN_ERR PFX "Failed to probe cores\n");
+	return err;
+}
+EXPORT_SYMBOL(ssb_probe_cores);
+
+int ssb_core_is_enabled(struct ssb *ssb)
+{
+	u32 val;
+
+	val = ssb_read32(ssb, SSB_TMSLOW);
+	val &= SSB_TMSLOW_CLOCK | SSB_TMSLOW_RESET | SSB_TMSLOW_REJECT;
+
+	return (val == SSB_TMSLOW_CLOCK);
+}
+EXPORT_SYMBOL(ssb_core_is_enabled);
+
+void ssb_core_enable(struct ssb *ssb, u32 core_specific_flags)
+{
+	u32 val;
+
+	ssb_core_disable(ssb, core_specific_flags);
+	ssb_write32(ssb, SSB_TMSLOW,
+		    SSB_TMSLOW_RESET | SSB_TMSLOW_CLOCK |
+		    SSB_TMSLOW_FGC | core_specific_flags);
+	/* flush */
+	ssb_read32(ssb, SSB_TMSLOW);
+	udelay(1);
+
+	/* Clear SERR if set. This is a hw bug workaround. */
+	if (ssb_read32(ssb, SSB_TMSHIGH) & SSB_TMSHIGH_SERR)
+		ssb_write32(ssb, SSB_TMSHIGH, 0);
+
+	val = ssb_read32(ssb, SSB_IMSTATE);
+	if (val & (SSB_IMSTATE_IBE | SSB_IMSTATE_TO)) {
+		val &= ~(SSB_IMSTATE_IBE | SSB_IMSTATE_TO);
+		ssb_write32(ssb, SSB_IMSTATE, val);
+	}
+
+	ssb_write32(ssb, SSB_TMSLOW,
+		    SSB_TMSLOW_CLOCK | SSB_TMSLOW_FGC |
+		    core_specific_flags);
+	/* flush */
+	ssb_read32(ssb, SSB_TMSLOW);
+	udelay(1);
+
+	ssb_write32(ssb, SSB_TMSLOW, SSB_TMSLOW_CLOCK |
+		    core_specific_flags);
+	/* flush */
+	ssb_read32(ssb, SSB_TMSLOW);
+	udelay(1);
+}
+EXPORT_SYMBOL(ssb_core_enable);
+
+static int ssb_wait_bit(struct ssb *ssb, u16 reg, u32 bitmask,
+			int timeout, int set)
+{
+	int i;
+	u32 val;
+
+	for (i = 0; i < timeout; i++) {
+		val = ssb_read32(ssb, reg);
+		if (set) {
+			if (val & bitmask)
+				return 0;
+		} else {
+			if (!(val & bitmask))
+				return 0;
+		}
+		udelay(10);
+	}
+	printk(KERN_ERR PFX "Timeout waiting for bitmask %08X on "
+			    "register %04X to %s.\n",
+	       bitmask, reg, (set ? "set" : "clear"));
+
+	return -ETIMEDOUT;
+}
+
+void ssb_core_disable(struct ssb *ssb, u32 core_specific_flags)
+{
+	if (ssb_read32(ssb, SSB_TMSLOW) & SSB_TMSLOW_RESET)
+		return;
+
+	ssb_write32(ssb, SSB_TMSLOW, SSB_TMSLOW_REJECT | SSB_TMSLOW_CLOCK);
+	ssb_wait_bit(ssb, SSB_TMSLOW, SSB_TMSLOW_REJECT, 1000, 1);
+	ssb_wait_bit(ssb, SSB_TMSHIGH, SSB_TMSHIGH_BUSY, 1000, 0);
+	ssb_write32(ssb, SSB_TMSLOW,
+		    SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK |
+		    SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET |
+		    core_specific_flags);
+	/* flush */
+	ssb_read32(ssb, SSB_TMSLOW);
+	udelay(1);
+
+	ssb_write32(ssb, SSB_TMSLOW,
+		    SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET |
+		    core_specific_flags);
+	/* flush */
+	ssb_read32(ssb, SSB_TMSLOW);
+	udelay(1);
+}
+EXPORT_SYMBOL(ssb_core_disable);
+
+static u32 ssb_pcie_read(struct ssb *ssb, u32 address)
+{
+	ssb_write32(ssb, 0x130, address);
+	return ssb_read32(ssb, 0x134);
+}
+
+static void ssb_pcie_write(struct ssb *ssb, u32 address, u32 data)
+{
+	ssb_write32(ssb, 0x130, address);
+	ssb_write32(ssb, 0x134, data);
+}
+
+static void ssb_pcie_mdio_write(struct ssb *ssb, u8 device,
+				u8 address, u16 data)
+{
+	const u16 mdio_control = 0x128;
+	const u16 mdio_data = 0x12C;
+	u32 v;
+	int i;
+
+	v = 0x80; /* Enable Preamble Sequence */
+	v |= 0x2; /* MDIO Clock Divisor */
+	ssb_write32(ssb, mdio_control, v);
+
+	v = (1 << 30); /* Start of Transaction */
+	v |= (1 << 28); /* Write Transaction */
+	v |= (1 << 17); /* Turnaround */
+	v |= (u32)device << 22;
+	v |= (u32)address << 18;
+	v |= data;
+	ssb_write32(ssb, mdio_data, v);
+	udelay(10);
+	for (i = 0; i < 10; i++) {
+		v = ssb_read32(ssb, mdio_control);
+		if (v & 0x100 /* Trans complete */)
+			break;
+		msleep(1);
+	}
+	ssb_write32(ssb, mdio_control, 0);
+}
+
+static void ssb_broadcast_value(struct ssb *ssb,
+				u32 address, u32 data)
+{
+	/* This is for both, PCI and ChipCommon core, so be careful. */
+	ssb_write32(ssb, 0x50, address);
+	ssb_read32(ssb, 0x0); /* flush */
+	ssb_write32(ssb, 0x54, data);
+	ssb_read32(ssb, 0x0); /* flush */
+}
+
+static int ssb_pcicore_commit_settings(struct ssb *ssb,
+				       struct ssb_core *chipcommon_core)
+{
+	struct ssb_core *old_core = NULL;
+	int err;
+
+	if (chipcommon_core) {
+		old_core = ssb->current_core;
+		err = ssb_switch_core(ssb, chipcommon_core);
+		if (err)
+			goto out;
+	}
+	/* This forces an update of the cached registers. */
+	ssb_broadcast_value(ssb, 0xFD8, 0);
+	if (old_core) {
+		err = ssb_switch_core(ssb, old_core);
+		if (err)
+			goto out;
+	}
+out:
+	return err;
+}
+
+int ssb_cores_connect(struct ssb *ssb, u32 coremask)
+{
+	struct ssb_core *old_core;
+	struct ssb_core *pci_core = NULL;
+	struct ssb_core *chipcommon_core = NULL;
+	u32 backplane_flag_nr;
+	u32 value;
+	int i, err;
+
+	might_sleep();
+
+	for (i = 0; i < ssb->nr_cores; i++) {
+		if (ssb->cores[i].cc == SSB_CC_PCI ||
+		    ssb->cores[i].cc == SSB_CC_PCIE)
+			pci_core = &(ssb->cores[i]);
+		else if (ssb->cores[i].cc == SSB_CC_CHIPCOMMON)
+			chipcommon_core = &(ssb->cores[i]);
+	}
+
+	value = ssb_read32(ssb, SSB_TPSFLAG);
+	backplane_flag_nr = value & SSB_TPSFLAG_BPFLAG;
+
+	old_core = ssb->current_core;
+	err = ssb_switch_core(ssb, pci_core);
+	if (err)
+		goto out;
+	if ((pci_core->rev >= 6) || (pci_core->cc == SSB_CC_PCIE)) {
+		err = ssb_pci_read_config32(ssb, SSB_PCI_IRQMASK, &value);
+		if (err)
+			goto out_switch_back;
+		value |= coremask << 8;
+		err = ssb_pci_write_config32(ssb, SSB_PCI_IRQMASK, value);
+		if (err)
+			goto out_switch_back;
+	} else {
+		value = ssb_read32(ssb, SSB_INTVEC);
+		value |= (1 << backplane_flag_nr);
+		ssb_write32(ssb, SSB_INTVEC, value);
+	}
+	if (pci_core->cc == SSB_CC_PCI) {
+		value = ssb_read32(ssb, 0x108 /* sbtopci2 */);
+		value |= 0x4 /* prefetch */ | 0x8 /* burst */;
+		ssb_write32(ssb, 0x108, value);
+		if (pci_core->rev < 5) {
+			value = ssb_read32(ssb, SSB_IMCFGLO);
+			value &= ~SSB_IMCFGLO_SERTO;
+			value |= 2;
+			value &= ~SSB_IMCFGLO_REQTO;
+			value |= 3 << SSB_IMCFGLO_REQTO_SHIFT;
+			ssb_write32(ssb, SSB_IMCFGLO, value);
+			err = ssb_pcicore_commit_settings(ssb, chipcommon_core);
+			if (err)
+				goto out_switch_back;
+		} else if (pci_core->rev >= 11) {
+			value = ssb_read32(ssb, 0x108 /* sbtopci2 */);
+			value |= 0x20 /* Memory Read Multiple */;
+			ssb_write32(ssb, 0x108, value);
+		}
+	} else {
+		if ((pci_core->rev == 0) || (pci_core->rev == 1)) {
+			/* TLP Workaround register. */
+			value = ssb_pcie_read(ssb, 0x4);
+			value |= 0x8;
+			ssb_pcie_write(ssb, 0x4, value);
+		}
+		if (pci_core->rev == 0) {
+			const u8 serdes_rx_device = 0x1F;
+
+			ssb_pcie_mdio_write(ssb, serdes_rx_device,
+					    2 /* Timer */, 0x8128);
+			ssb_pcie_mdio_write(ssb, serdes_rx_device,
+					    6 /* CDR */, 0x0100);
+			ssb_pcie_mdio_write(ssb, serdes_rx_device,
+					    7 /* CDR BW */, 0x1466);
+		} else if (pci_core->rev == 1) {
+			/* DLLP Link Control register. */
+			value = ssb_pcie_read(ssb, 0x100);
+			value |= 0x40;
+			ssb_pcie_write(ssb, 0x100, value);
+		}
+	}
+out_switch_back:
+	err = ssb_switch_core(ssb, old_core);
+out:
+	return err;
+}
+EXPORT_SYMBOL(ssb_cores_connect);
+
+
+MODULE_DESCRIPTION("Sonics Silicon Backplane driver");
+MODULE_LICENSE("GPL");
Index: wireless-dev/include/linux/ssb.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ wireless-dev/include/linux/ssb.h	2006-08-14 23:15:38.000000000 +0200
@@ -0,0 +1,309 @@
+#ifndef LINUX__SONICS_SILICON_BACKPLANE_H_
+#define LINUX__SONICS_SILICON_BACKPLANE_H_
+
+/* Sonics SiliconBackplane support routines. */
+
+#include <linux/types.h>
+
+/* SSB PCI config space registers. */
+#define SSB_PMCSR		0x44
+#define  SSB_PE			0x100
+#define	SSB_BAR0_WIN		0x80
+#define	SSB_BAR1_WIN		0x84
+#define	SSB_SPROM_CONTROL	0x88
+#define	SSB_BAR1_CONTROL	0x8c
+#define SSB_PCI_IRQS		0x90
+#define SSB_PCI_IRQMASK		0x94
+#define SSB_BACKPLANE_IRQS	0x98
+#define SSB_GPIO_IN		0xB0
+#define SSB_GPIO_OUT		0xB4
+#define SSB_GPIO_OUT_ENABLE	0xB8
+
+#define SSB_BAR0_MAX_RETRIES	50
+
+/* SSB core and host control registers. */
+#define SSB_CONTROL		0x0000
+#define SSB_ARBCONTROL		0x0010
+#define SSB_ISTAT		0x0020
+#define SSB_IMASK		0x0024
+#define SSB_MBOX		0x0028
+#define SSB_BCAST_ADDR		0x0050
+#define SSB_BCAST_DATA		0x0054
+#define SSB_PCI_TRANS_0		0x0100
+#define SSB_PCI_TRANS_1		0x0104
+#define SSB_PCI_TRANS_2		0x0108
+#define SSB_SPROM		0x0800
+
+#define SSB_PCI_MEM		0x00000000
+#define SSB_PCI_IO		0x00000001
+#define SSB_PCI_CFG0		0x00000002
+#define SSB_PCI_CFG1		0x00000003
+#define SSB_PCI_PREF		0x00000004
+#define SSB_PCI_BURST		0x00000008
+#define SSB_PCI_MASK0		0xfc000000
+#define SSB_PCI_MASK1		0xfc000000
+#define SSB_PCI_MASK2		0xc0000000
+
+/* Silicon backplane register definitions */
+#define SSB_IPSFLAG		0x0F08
+#define SSB_TPSFLAG		0x0F18
+#define  SSB_TPSFLAG_BPFLAG	0x0000003F /* Backplane flag # */
+#define  SSB_TPSFLAG_ALWAYSIRQ	0x00000040 /* IRQ is always sent on the Backplane */
+#define SSB_TMERRLOGA		0x0F48
+#define SSB_TMERRLOG		0x0F50
+#define SSB_ADMATCH3		0x0F60
+#define SSB_ADMATCH2		0x0F68
+#define SSB_ADMATCH1		0x0F70
+#define SSB_IMSTATE		0x0F90     /* SB Initiator Agent State */
+#define  SSB_IMSTATE_PC		0x0000000f /* Pipe Count */
+#define  SSB_IMSTATE_AP_MASK	0x00000030 /* Arbitration Priority */
+#define  SSB_IMSTATE_AP_BOTH	0x00000000 /* Use both timeslices and token */
+#define  SSB_IMSTATE_AP_TS	0x00000010 /* Use timeslices only */
+#define  SSB_IMSTATE_AP_TK	0x00000020 /* Use token only */
+#define  SSB_IMSTATE_AP_RSV	0x00000030 /* Reserved */
+#define  SSB_IMSTATE_IBE	0x00020000 /* In Band Error */
+#define  SSB_IMSTATE_TO		0x00040000 /* Timeout */
+#define SSB_INTVEC		0x0F94     /* SB Interrupt Mask */
+#define  SSB_INTVEC_PCI		0x00000001 /* Enable interrupts for PCI */
+#define  SSB_INTVEC_ENET0	0x00000002 /* Enable interrupts for enet 0 */
+#define  SSB_INTVEC_ILINE20	0x00000004 /* Enable interrupts for iline20 */
+#define  SSB_INTVEC_CODEC	0x00000008 /* Enable interrupts for v90 codec */
+#define  SSB_INTVEC_USB		0x00000010 /* Enable interrupts for usb */
+#define  SSB_INTVEC_EXTIF	0x00000020 /* Enable interrupts for external i/f */
+#define  SSB_INTVEC_ENET1	0x00000040 /* Enable interrupts for enet 1 */
+#define SSB_TMSLOW		0x0F98     /* SB Target State Low */
+#define  SSB_TMSLOW_RESET	0x00000001 /* Reset */
+#define  SSB_TMSLOW_REJECT	0x00000002 /* Reject */
+#define  SSB_TMSLOW_CLOCK	0x00010000 /* Clock Enable */
+#define  SSB_TMSLOW_FGC		0x00020000 /* Force Gated Clocks On */
+#define  SSB_TMSLOW_PE		0x40000000 /* Power Management Enable */
+#define  SSB_TMSLOW_BE		0x80000000 /* BIST Enable */
+#define SSB_TMSHIGH		0x0F9C     /* SB Target State High */
+#define  SSB_TMSHIGH_SERR	0x00000001 /* S-error */
+#define  SSB_TMSHIGH_INT	0x00000002 /* Interrupt */
+#define  SSB_TMSHIGH_BUSY	0x00000004 /* Busy */
+#define  SSB_TMSHIGH_GCR	0x20000000 /* Gated Clock Request */
+#define  SSB_TMSHIGH_BISTF	0x40000000 /* BIST Failed */
+#define  SSB_TMSHIGH_BISTD	0x80000000 /* BIST Done */
+#define SSB_BWA0		0x0FA0
+#define SSB_IMCFGLO		0x0FA8
+#define  SSB_IMCFGLO_SERTO	0x00000007 /* Service timeout */
+#define  SSB_IMCFGLO_REQTO	0x00000070 /* Request timeout */
+#define  SSB_IMCFGLO_REQTO_SHIFT	4
+#define  SSB_IMCFGLO_CONNID	0x00FF0000 /* Connection ID */
+#define  SSB_IMCFGLO_CONNID_SHIFT	16
+#define SSB_IMCFGHI		0x0FAC
+#define SSB_BCONFIG		0x0FC0
+#define SSB_BSTATE		0x0FC8
+#define SSB_ACTCFG		0x0FD8
+#define SSB_FLAGST		0x0FE8
+#define SSB_IDLOW		0x0FF8
+//TODO
+#define SSB_IDHIGH		0x0FFC     /* SB Identification High */
+#define  SSB_IDHIGH_RC_MASK	0x0000000f /* Revision Code */
+#define  SSB_IDHIGH_CC_MASK	0x0000fff0 /* Core Code */
+#define  SSB_IDHIGH_CC_SHIFT	4
+#define  SSB_IDHIGH_VC_MASK	0xffff0000 /* Vendor Code */
+#define  SSB_IDHIGH_VC_SHIFT	16
+
+/* Core Code values. */
+#define SSB_CC_CHIPCOMMON	0x800
+#define SSB_CC_ILINE20		0x801
+#define SSB_CC_SDRAM		0x803
+#define SSB_CC_PCI		0x804
+#define SSB_CC_MIPS		0x805
+#define SSB_CC_ETHERNET		0x806
+#define SSB_CC_V90		0x807
+#define SSB_CC_USB11_HOSTDEV	0x808
+#define SSB_CC_ADSL		0x809
+#define SSB_CC_ILINE100		0x80A
+#define SSB_CC_IPSEC		0x80B
+#define SSB_CC_PCMCIA		0x80D
+#define SSB_CC_INTERNAL_MEM	0x80E
+#define SSB_CC_MEMC_SDRAM	0x80F
+#define SSB_CC_EXTIF		0x811
+#define SSB_CC_80211		0x812
+#define SSB_CC_MIPS_3302	0x816
+#define SSB_CC_USB11_HOST	0x817
+#define SSB_CC_USB11_DEV	0x818
+#define SSB_CC_USB20_HOST	0x819
+#define SSB_CC_USB20_DEV	0x81A
+#define SSB_CC_SDIO_HOST	0x81B
+#define SSB_CC_ROBOSWITCH	0x81C
+#define SSB_CC_PARA_ATA		0x81D
+#define SSB_CC_SATA_XORDMA	0x81E
+#define SSB_CC_ETHERNET_GBIT	0x81F
+#define SSB_CC_PCIE		0x820
+#define SSB_CC_MIMO_PHY		0x821
+#define SSB_CC_SRAM_CTRLR	0x822
+#define SSB_CC_MINI_MACPHY	0x823
+#define SSB_CC_ARM_1176		0x824
+#define SSB_CC_ARM_7TDMI	0x825
+
+/* ChipCommon registers. */
+#define SSB_CHIPCOMMON_CHIPID		0x0000
+#define  SSB_CHIPCOMMON_IDMASK		0x0000FFFF
+#define  SSB_CHIPCOMMON_REVMASK		0x000F0000
+#define  SSB_CHIPCOMMON_REVSHIFT	16
+#define  SSB_CHIPCOMMON_PACKMASK	0x00F00000
+#define  SSB_CHIPCOMMON_PACKSHIFT	20
+#define  SSB_CHIPCOMMON_NRCORESMASK	0x0F000000
+#define  SSB_CHIPCOMMON_NRCORESSHIFT	24
+#define SSB_CHIPCOMMON_CAPABILITIES 	0x0004
+#define SSB_CHIPCOMMON_CORECTL		0x0008
+#define SSB_CHIPCOMMON_BIST		0x000C
+#define SSB_CHIPCOMMON_PLLONDELAY	0x00B0
+#define SSB_CHIPCOMMON_FREFSELDELAY	0x00B4
+#define SSB_CHIPCOMMON_SLOWCLKCTL	0x00B8
+#define SSB_CHIPCOMMON_SYSCLKCTL	0x00C0
+
+
+struct pci_dev;
+
+
+/**
+ * struct ssb_core - Sonics Silicon Backplane core
+ * @cc:		CoreCode ID. See SSB_CC_???
+ * @vendor:	Core vendor ID number.
+ * @rev:	Core revision code.
+ * @index:	Index in the ssb->cores array.
+ * @priv:	Private data for use by the driver.
+ * 		This is not touched by the ssb subsystem (except
+ * 		initialized to NULL in ssb_probe_cores()).
+ */
+struct ssb_core {
+	u16 cc;
+	u16 vendor;
+	u8 rev;
+	u8 index;
+
+	void *priv;
+};
+
+/**
+ * struct ssb - Sonics Silicon Backplane
+ * @chip_id:			Chip ID. Assigned by the ssb subsystem.
+ * @chip_rev:			Chip Revision. Assigned by the ssb subsystem.
+ * @chip_package:		Chip Package. Assigned by the ssb subsystem.
+ * @cores:			Array of all available cores.
+ * @nr_cores:			Arraysize of "cores".
+ * @current_core:		Pointer to the currently mapped core. Don't
+ * 				modify directly. Use ssb_switch_core().
+ *
+ * @current_core_offset:	Internal. Use ssb_core_offset().
+ * @pci_dev:			Internal.
+ * @mmio:			Internal. Pointer to the MMIO area.
+ */
+struct ssb {
+	u16 chip_id;
+	u8 chip_rev;
+	u8 chip_package;
+	u32 chipcommon_capabilities;
+
+	struct ssb_core	*cores;
+	int nr_cores;
+	struct ssb_core *current_core;
+#ifdef CONFIG_BCM947XX
+	u16 current_core_offset;
+#endif
+	struct pci_dev *pci_dev;
+	void __iomem *mmio;
+};
+
+/**
+ * ssb_core_offset - Get the MMIO corespecific offset.
+ * Add this offset to all MMIO offsets on every MMIO
+ * access on the core.
+ * @ssb:	Pointer to struct ssb.
+ */
+static inline u16 ssb_core_offset(struct ssb *ssb)
+{
+#ifdef CONFIG_BCM947XX
+	return ssb->current_core_offset;
+#else
+	return 0;
+#endif
+}
+
+/**
+ * ssb_alloc - Allocate struct ssb.
+ * This does not init hardware. May fail and return NULL.
+ * @pci_dev:	Pointer to the PCI device.
+ * @mmio:	Pointer to the MMIO area of the device.
+ */
+struct ssb * ssb_alloc(struct pci_dev *pci_dev,
+		       void __iomem *mmio);
+/** ssb_free - Free struct ssb. */
+void ssb_free(struct ssb *ssb);
+
+/**
+ * struct ssb_nrcores_elem - Array element of the
+ * "number of cores" fallback array.
+ * This array is browsed, if there is no ChipCommon rev >= 4
+ * core available.
+ * @chip_id_key:	The CHIPID key value for browsing the array.
+ * @nr_cores_value:	The number of available cores on this CHIPID.
+ */
+struct ssb_nrcores_elem {
+	u16 chip_id_key;
+	u8 nr_cores_value;
+};
+
+/**
+ * ssb_probe_cores - Search and probe all available cores.
+ * Returns 0 on success or an error code on failure.
+ * @ssb:		Pointer to struct ssb.
+ * @chipid_fallback:	Fallback CHIPID value. This is only used,
+ * 			if there is no ChipCommon to read the
+ * 			CHIPID from.
+ * @nrcores_fallback:	An array of struct ssb_nrcores_elem to determine
+ * 			the number of cores on a given CHIPID, if there
+ * 			is no ChipCommon rev >= 4.
+ * @nrcores_fb_size:	ARRAY_SIZE(nrcores_fallback)
+ */
+int ssb_probe_cores(struct ssb *ssb,
+		    u16 chipid_fallback,
+		    const struct ssb_nrcores_elem *nrcores_fallback,
+		    size_t nrcores_fb_size);
+/**
+ * ssb_switch_core - Switch the "current_core" to another
+ * one out of the ssb->cores array.
+ * Returns 0 on success or an error code on failure.
+ * @ssb:	Pointer to struct ssb.
+ * @new_core:	The new core to switch to.
+ */
+int ssb_switch_core(struct ssb *ssb,
+		    struct ssb_core *new_core);
+
+/**
+ * ssb_core_is_enabled - Check if current_core is enabled in hardware.
+ * Returns a boolean.
+ * @ssb:	Pointer to struct ssb.
+ */
+int ssb_core_is_enabled(struct ssb *ssb);
+/**
+ * ssb_core_enable - Reset and enable current_core.
+ * @ssb:	Pointer to struct ssb.
+ * @core_specific_flags:	Additional SSB_TMSLOW flags for
+ * 				this core. Pass 0 for none.
+ */
+void ssb_core_enable(struct ssb *ssb, u32 core_specific_flags);
+/**
+ * ssb_core_disable - Disable current_core.
+ * @ssb:	Pointer to struct ssb.
+ * @core_specific_flags:	Additional SSB_TMSLOW flags for
+ * 				this core. Pass 0 for none.
+ */
+void ssb_core_disable(struct ssb *ssb, u32 core_specific_flags);
+/**
+ * ssb_cores_connect - Connect I/O cores to the backplane.
+ * Cores need to be connected to the backplane in order
+ * to route interrupts, for example.
+ * This function might sleep.
+ * Returns 0 on success or an error code on failure.
+ * @ssb:	Pointer to struct ssb.
+ * @coremask:	Bitmask of cores to connect.
+ */
+int ssb_cores_connect(struct ssb *ssb, u32 coremask);
+
+#endif /* LINUX__SONICS_SILICON_BACKPLANE_H_ */


-- 
Greetings Michael.

  reply	other threads:[~2006-08-14 22:23 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-08-14 22:14 [patch RFC 0/3] Sonics Silicon Backplane module Michael Buesch
2006-08-14 22:15 ` Michael Buesch [this message]
2006-08-14 22:17 ` [patch RFC 2/3] bcm43xx-d80211: convert to ssb module Michael Buesch
     [not found] ` <200608150014.19661.mb-fseUSCV1ubazQB+pC5nmwQ@public.gmane.org>
2006-08-14 22:18   ` [patch RFC 3/3] b44: " Michael Buesch
2006-08-15 12:12     ` John W. Linville
2006-08-15 14:14       ` Michael Buesch
     [not found]         ` <200608151614.16640.mb-fseUSCV1ubazQB+pC5nmwQ@public.gmane.org>
2006-08-15 14:33           ` John W. Linville
2006-08-15 14:49             ` Michael Buesch

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=200608150015.38510.mb@bu3sch.de \
    --to=mb@bu3sch.de \
    --cc=bcm43xx-dev@lists.berlios.de \
    --cc=netdev@vger.kernel.org \
    --cc=zambrano@broadcom.com \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.