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.
next prev parent 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.