Hi BCM43xx hackers.

I'm one of the OpenWrt developers and I'm currently working on integrating your driver into our development branch. I've written a patch which adds support for a BCM43xx core integrated into the main SB of the BCM47xx SoC. It applies against the dscape branch, which I intend to use, but it should be easy to port it to trunk. Some people on irc.sipsolutions already reviewed an earlier version, so it would be nice if you could commit this version to SVN. While testing it, I was able to associate with another AP, but couldn't transfer any data (had to hack some of the rate stuff for testing, this might be the problem).

Have fun,

Felix
Index: bcm43xx_main.h
===================================================================
--- bcm43xx_main.h	(revision 994)
+++ bcm43xx_main.h	(working copy)
@@ -33,7 +33,26 @@
 
 #include "bcm43xx.h"
 
+#ifdef CONFIG_BCM947XX
+#define atoi(str) simple_strtoul(((str != NULL) ? str : ""), NULL, 0)
 
+static inline void e_aton(char *str, char *dest)
+{
+	int i = 0;
+	u16 *d = (u16 *) dest;
+
+	for (;;) {
+		dest[i++] = (char) simple_strtoul(str, NULL, 16);
+		str += 2;
+		if (!*str++ || i == 6)
+			break;
+	}
+	for (i = 0; i < 3; i++)
+		d[i] = cpu_to_be16(d[i]);
+}
+#endif
+
+
 #define _bcm43xx_declare_plcp_hdr(size) \
 	struct bcm43xx_plcp_hdr##size {			\
 		union {					\
Index: bcm43xx_dma.c
===================================================================
--- bcm43xx_dma.c	(revision 994)
+++ bcm43xx_dma.c	(working copy)
@@ -338,7 +338,7 @@
 	meta->skb = skb;
 	meta->dmaaddr = dmaaddr;
 	skb->dev = ring->bcm->net_dev;
-	desc_addr = (u32)(dmaaddr + BCM43xx_DMA_DMABUSADDROFFSET);
+	desc_addr = (u32)(dmaaddr + ring->memoffset);
 	desc_ctl = (BCM43xx_DMADTOR_BYTECNT_MASK &
 		    (u32)(ring->rx_buffersize - ring->frameoffset));
 	if (slot == ring->nr_slots - 1)
@@ -407,7 +407,7 @@
 		/* Set Transmit Descriptor ring address. */
 		bcm43xx_write32(ring->bcm,
 				ring->mmio_base + BCM43xx_DMA_TX_DESC_RING,
-				ring->dmabase + BCM43xx_DMA_DMABUSADDROFFSET);
+				ring->dmabase + ring->memoffset);
 	} else {
 		err = alloc_initial_descbuffers(ring);
 		if (err)
@@ -421,7 +421,7 @@
 		/* Set Receive Descriptor ring address. */
 		bcm43xx_write32(ring->bcm,
 				ring->mmio_base + BCM43xx_DMA_RX_DESC_RING,
-				ring->dmabase + BCM43xx_DMA_DMABUSADDROFFSET);
+				ring->dmabase + ring->memoffset);
 		/* Init the descriptor pointer. */
 		bcm43xx_write32(ring->bcm,
 				ring->mmio_base + BCM43xx_DMA_RX_DESC_INDEX,
@@ -496,6 +496,13 @@
 	if (!ring->meta)
 		goto err_kfree_ring;
 
+	ring->memoffset = BCM43xx_DMA_DMABUSADDROFFSET;
+#ifdef CONFIG_BCM947XX
+	if (bcm->pci_dev->bus->number == 0)
+		ring->memoffset = 0;
+#endif
+	
+	
 	spin_lock_init(&ring->lock);
 	ring->bcm = bcm;
 	ring->nr_slots = nr_descriptor_slots;
@@ -808,7 +815,7 @@
 		return -ENOMEM;
 	}
 
-	desc_addr = (u32)(meta->dmaaddr + BCM43xx_DMA_DMABUSADDROFFSET);
+	desc_addr = (u32)(meta->dmaaddr + ring->memoffset);
 	desc_ctl = BCM43xx_DMADTOR_FRAMESTART |
 		   (BCM43xx_DMADTOR_BYTECNT_MASK & (u32)(hdr_skb->len));
 	if (slot == ring->nr_slots - 1)
@@ -837,7 +844,7 @@
 		return -ENOMEM;
 	}
 
-	desc_addr = (u32)(meta->dmaaddr + BCM43xx_DMA_DMABUSADDROFFSET);
+	desc_addr = (u32)(meta->dmaaddr + ring->memoffset);
 	desc_ctl = (BCM43xx_DMADTOR_BYTECNT_MASK & (u32)(skb->len));
 	if (slot == ring->nr_slots - 1)
 		desc_ctl |= BCM43xx_DMADTOR_DTABLEEND;
Index: bcm43xx_dma.h
===================================================================
--- bcm43xx_dma.h	(revision 994)
+++ bcm43xx_dma.h	(working copy)
@@ -123,6 +123,8 @@
 	struct bcm43xx_private *bcm;
 	/* Kernel virtual base address of the ring memory. */
 	struct bcm43xx_dmadesc *vbase;
+	/* DMA memory offset */
+	dma_addr_t memoffset;
 	/* (Unadjusted) DMA base bus-address of the ring memory. */
 	dma_addr_t dmabase;
 	/* Meta data about all descriptors. */
Index: bcm43xx_debugfs.c
===================================================================
--- bcm43xx_debugfs.c	(revision 994)
+++ bcm43xx_debugfs.c	(working copy)
@@ -88,7 +88,7 @@
 		pci_dev->vendor, pci_dev->device);
 	fappend("subsystem_vendor: 0x%04x   subsystem_device: 0x%04x\n",
 		pci_dev->subsystem_vendor, pci_dev->subsystem_device);
-	fappend("IRQ: %d\n", pci_dev->irq);
+	fappend("IRQ: %d\n", bcm->irq);
 	fappend("mmio_addr: 0x%p   mmio_len: %u\n", bcm->mmio_addr, bcm->mmio_len);
 	fappend("chip_id: 0x%04x   chip_rev: 0x%02x\n", bcm->chip_id, bcm->chip_rev);
 	if ((bcm->core_80211[0].rev >= 3) && (bcm43xx_read32(bcm, 0x0158) & (1 << 16)))
Index: bcm43xx_main.c
===================================================================
--- bcm43xx_main.c	(revision 994)
+++ bcm43xx_main.c	(working copy)
@@ -57,6 +57,10 @@
 MODULE_AUTHOR("Michael Buesch");
 MODULE_LICENSE("GPL");
 
+#ifdef CONFIG_BCM947XX
+extern char *nvram_get(char *name);
+#endif
+
 /* Module parameters */
 static int modparam_pio;
 module_param_named(pio, modparam_pio, int, 0444);
@@ -107,6 +111,11 @@
 	 * http://openfacts.berlios.de/index-en.phtml?title=Bcm43xxDevices
 	 */
 
+#ifdef CONFIG_BCM947XX
+	/* SB bus on BCM947xx */
+	{ PCI_VENDOR_ID_BROADCOM, 0x0800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+#endif
+	
 	/* Broadcom 4303 802.11b */
 	{ PCI_VENDOR_ID_BROADCOM, 0x4301, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 
@@ -933,19 +942,43 @@
 	return crc;
 }
 
+
 static int bcm43xx_read_sprom(struct bcm43xx_private *bcm)
 {
 	int i;
 	u16 value;
 	u16 *sprom;
 	u8 crc, expected_crc;
+#ifdef CONFIG_BCM947XX
+	char *c;
+#endif
 
-	sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(u16),
+	sprom = kzalloc(BCM43xx_SPROM_SIZE * sizeof(u16),
 			GFP_KERNEL);
 	if (!sprom) {
 		printk(KERN_ERR PFX "read_sprom OOM\n");
 		return -ENOMEM;
 	}
+#ifdef CONFIG_BCM947XX
+	sprom[BCM43xx_SPROM_BOARDFLAGS2] = atoi(nvram_get("boardflags2"));
+	sprom[BCM43xx_SPROM_BOARDFLAGS] = atoi(nvram_get("boardflags"));
+
+	if ((c = nvram_get("il0macaddr")) != NULL)
+		e_aton(c, (char *) &(sprom[BCM43xx_SPROM_IL0MACADDR]));
+
+	if ((c = nvram_get("et1macaddr")) != NULL)
+		e_aton(c, (char *) &(sprom[BCM43xx_SPROM_ET1MACADDR]));
+
+	sprom[BCM43xx_SPROM_PA0B0] = atoi(nvram_get("pa0b0"));
+	sprom[BCM43xx_SPROM_PA0B1] = atoi(nvram_get("pa0b1"));
+	sprom[BCM43xx_SPROM_PA0B2] = atoi(nvram_get("pa0b2"));
+
+	sprom[BCM43xx_SPROM_PA1B0] = atoi(nvram_get("pa1b0"));
+	sprom[BCM43xx_SPROM_PA1B1] = atoi(nvram_get("pa1b1"));
+	sprom[BCM43xx_SPROM_PA1B2] = atoi(nvram_get("pa1b2"));
+
+	sprom[BCM43xx_SPROM_BOARDREV] = atoi(nvram_get("boardrev"));
+#else
 	for (i = 0; i < BCM43xx_SPROM_SIZE; i++)
 		sprom[i] = bcm43xx_read16(bcm, BCM43xx_SPROM_BASE + (i * 2));
 
@@ -957,6 +990,7 @@
 					"(0x%02X, expected: 0x%02X)\n",
 		       crc, expected_crc);
 	}
+#endif
 
 	/* boardflags2 */
 	value = sprom[BCM43xx_SPROM_BOARDFLAGS2];
@@ -1053,6 +1087,7 @@
 	bcm->sprom.antennagain_bgphy = (value & 0x00FF) * 4;
 
 	kfree(sprom);
+
 	return 0;
 }
 
@@ -1301,6 +1336,12 @@
 			continue;
 		}
 		_get_current_core(bcm, &current_core);
+#ifdef CONFIG_BCM947XX
+		if (bcm->pci_dev->bus->number == 0)
+			bcm->current_core_offset = 0x1000 * core;
+		else
+			bcm->current_core_offset = 0;
+#endif
 	}
 
 	assert(err == 0);
@@ -1454,6 +1495,7 @@
 	u32 flags = 0x00040000;
 
 	if ((bcm43xx_core_enabled(bcm)) && (!bcm->pio_mode)) {
+#ifndef CONFIG_BCM947XX
 		/* reset all used DMA controllers. */
 		bcm43xx_dmacontroller_tx_reset(bcm, BCM43xx_MMIO_DMA1_BASE);
 		bcm43xx_dmacontroller_tx_reset(bcm, BCM43xx_MMIO_DMA2_BASE);
@@ -1462,6 +1504,7 @@
 		bcm43xx_dmacontroller_rx_reset(bcm, BCM43xx_MMIO_DMA1_BASE);
 		if (bcm->current_core->rev < 5)
 			bcm43xx_dmacontroller_rx_reset(bcm, BCM43xx_MMIO_DMA4_BASE);
+#endif
 	}
 	if (bcm->shutting_down) {
 		bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
@@ -2249,10 +2292,21 @@
 	unsigned int i;
 	u32 data;
 
-	res = request_irq(bcm->pci_dev->irq, bcm43xx_interrupt_handler,
+	bcm->irq = bcm->pci_dev->irq;
+#ifdef CONFIG_BCM947XX
+	if (bcm->pci_dev->bus->number == 0) {
+		struct pci_dev *d = NULL;
+		/* FIXME: we will probably need more device IDs here... */
+		d = pci_find_device(PCI_VENDOR_ID_BROADCOM, 0x4324, NULL);
+		if (d != NULL) {
+			bcm->irq = d->irq;
+		}
+	}
+#endif
+	res = request_irq(bcm->irq, bcm43xx_interrupt_handler,
 			  SA_SHIRQ, DRV_NAME, bcm);
 	if (res) {
-		printk(KERN_ERR PFX "Cannot register IRQ%d\n", bcm->pci_dev->irq);
+		printk(KERN_ERR PFX "Cannot register IRQ%d\n", bcm->irq);
 		return -EFAULT;
 	}
 	bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, 0xffffffff);
@@ -2266,7 +2320,7 @@
 		if (i >= BCM43xx_IRQWAIT_MAX_RETRIES) {
 			printk(KERN_ERR PFX "Card IRQ register not responding. "
 					    "Giving up.\n");
-			free_irq(bcm->pci_dev->irq, bcm);
+			free_irq(bcm->irq, bcm);
 			return -ENODEV;
 		}
 		udelay(10);
@@ -2517,7 +2571,7 @@
 {
 	bcm43xx_radio_turn_off(bcm);
 	bcm43xx_gpio_cleanup(bcm);
-	free_irq(bcm->pci_dev->irq, bcm);
+	free_irq(bcm->irq, bcm);
 }
 
 /* Initialize the chip
@@ -2650,7 +2704,7 @@
 err_gpio_cleanup:
 	bcm43xx_gpio_cleanup(bcm);
 err_free_irq:
-	free_irq(bcm->pci_dev->irq, bcm);
+	free_irq(bcm->irq, bcm);
 	goto out;
 }
 	
@@ -2738,6 +2792,10 @@
 			chip_id_16 = 0x4610;
 		else if ((pci_device >= 0x4710) && (pci_device <= 0x4715))
 			chip_id_16 = 0x4710;
+#ifdef CONFIG_BCM947XX
+		else if ((pci_device >= 0x4320) && (pci_device <= 0x4325))
+			chip_id_16 = 0x4309;
+#endif
 		else {
 			/* Presumably devices not listed above are not
 			 * put into the pci device table for this driver,
@@ -2879,6 +2937,7 @@
 			case 4:
 			case 5:
 			case 6:
+			case 7:
 			case 9:
 				break;
 			default:
@@ -3197,7 +3256,7 @@
 	u32 backplane_flag_nr;
 	u32 value;
 	struct bcm43xx_coreinfo *old_core;
-	int err;
+	int err = 0;
 
 	value = bcm43xx_read32(bcm, BCM43xx_CIR_SBTPSFLAG);
 	backplane_flag_nr = value & BCM43xx_BACKPLANE_FLAG_NR_MASK;
@@ -4281,6 +4340,7 @@
 		err = -ENODEV;
 		goto err_pci_disable;
 	}
+#ifndef CONFIG_BCM947XX
 	if (mmio_len != BCM43xx_IO_SIZE) {
 		printk(KERN_ERR PFX
 		       "%s: invalid PCI mem region size(s), aborting\n",
@@ -4288,6 +4348,7 @@
 		err = -ENODEV;
 		goto err_pci_disable;
 	}
+#endif
 
 	err = pci_request_regions(pci_dev, DRV_NAME);
 	if (err) {
@@ -4730,7 +4791,7 @@
 	unsigned long flags;
 
 	local_irq_save(flags);
-	bcm43xx_interrupt_handler(bcm->pci_dev->irq, bcm, NULL);
+	bcm43xx_interrupt_handler(bcm->irq, bcm, NULL);
 	local_irq_restore(flags);
 }
 #endif /* CONFIG_NET_POLL_CONTROLLER */
@@ -4771,6 +4832,11 @@
 	struct ieee80211_hw *ieee;
 	int err = -ENOMEM;
 
+#ifdef CONFIG_BCM947XX
+	if ((pdev->bus->number == 0) && (pdev->device != 0x0800))
+		return -ENODEV;
+#endif
+	
 #ifdef DEBUG_SINGLE_DEVICE_ONLY
 	if (strcmp(pci_name(pdev), DEBUG_SINGLE_DEVICE_ONLY))
 		return -ENODEV;
Index: bcm43xx.h
===================================================================
--- bcm43xx.h	(revision 994)
+++ bcm43xx.h	(working copy)
@@ -589,6 +589,12 @@
 #define BCM43xx_COREFLAG_ENABLED	(1 << 1)
 #define BCM43xx_COREFLAG_INITIALIZED	(1 << 2)
 
+#ifdef CONFIG_BCM947XX
+#define core_offset(bcm) (bcm)->current_core_offset
+#else
+#define core_offset(bcm) 0
+#endif
+
 struct bcm43xx_coreinfo {
 	/** Driver internal flags. See BCM43xx_COREFLAG_* */
 	u32 flags;
@@ -646,6 +652,7 @@
 
 	struct net_device *net_dev;
 	struct pci_dev *pci_dev;
+	unsigned int irq;
 
 	void __iomem *mmio_addr;
 	unsigned int mmio_len;
@@ -683,6 +690,10 @@
 
 	/* The currently active core. NULL if not initialized, yet. */
 	struct bcm43xx_coreinfo *current_core;
+#ifdef CONFIG_BCM947XX
+	/** current core memory offset */
+	u32 current_core_offset;
+#endif
 	struct bcm43xx_coreinfo *active_80211_core;
 	/* coreinfo structs for all possible cores follow.
 	 * Note that a core might not exist.
@@ -798,7 +809,7 @@
 {
 	u16 value;
 
-	value = ioread16(bcm->mmio_addr + offset);
+	value = ioread16(bcm->mmio_addr + core_offset(bcm) + offset);
 	if (unlikely(atomic_read(&bcm->mmio_print_cnt) > 0)) {
 		printk(KERN_INFO PFX "ioread16   offset: 0x%04x, value: 0x%04x\n",
 		       offset, value);
@@ -810,7 +821,7 @@
 static inline
 void bcm43xx_write16(struct bcm43xx_private *bcm, u16 offset, u16 value)
 {
-	iowrite16(value, bcm->mmio_addr + offset);
+	iowrite16(value, bcm->mmio_addr + core_offset(bcm) + offset);
 	if (unlikely(atomic_read(&bcm->mmio_print_cnt) > 0)) {
 		printk(KERN_INFO PFX "iowrite16  offset: 0x%04x, value: 0x%04x\n",
 		       offset, value);
@@ -822,7 +833,7 @@
 {
 	u32 value;
 
-	value = ioread32(bcm->mmio_addr + offset);
+	value = ioread32(bcm->mmio_addr + core_offset(bcm) + offset);
 	if (unlikely(atomic_read(&bcm->mmio_print_cnt) > 0)) {
 		printk(KERN_INFO PFX "ioread32   offset: 0x%04x, value: 0x%08x\n",
 		       offset, value);
@@ -834,7 +845,7 @@
 static inline
 void bcm43xx_write32(struct bcm43xx_private *bcm, u16 offset, u32 value)
 {
-	iowrite32(value, bcm->mmio_addr + offset);
+	iowrite32(value, bcm->mmio_addr + core_offset(bcm) + offset);
 	if (unlikely(atomic_read(&bcm->mmio_print_cnt) > 0)) {
 		printk(KERN_INFO PFX "iowrite32  offset: 0x%04x, value: 0x%08x\n",
 		       offset, value);
@@ -906,10 +917,10 @@
 
 #else /* BCM43xx_DEBUG */
 
-#define bcm43xx_read16(bcm, offset)		ioread16((bcm)->mmio_addr + (offset))
-#define bcm43xx_write16(bcm, offset, value)	iowrite16((value), (bcm)->mmio_addr + (offset))
-#define bcm43xx_read32(bcm, offset)		ioread32((bcm)->mmio_addr + (offset))
-#define bcm43xx_write32(bcm, offset, value)	iowrite32((value), (bcm)->mmio_addr + (offset))
+#define bcm43xx_read16(bcm, offset)		ioread16((bcm)->mmio_addr + core_offset(bcm) + (offset))
+#define bcm43xx_write16(bcm, offset, value)	iowrite16((value), (bcm)->mmio_addr + core_offset(bcm) + (offset))
+#define bcm43xx_read32(bcm, offset)		ioread32((bcm)->mmio_addr + core_offset(bcm) + (offset))
+#define bcm43xx_write32(bcm, offset, value)	iowrite32((value), (bcm)->mmio_addr + core_offset(bcm) + (offset))
 #define bcm43xx_pci_read_config16(bcm, o, v)	pci_read_config_word((bcm)->pci_dev, (o), (v))
 #define bcm43xx_pci_read_config32(bcm, o, v)	pci_read_config_dword((bcm)->pci_dev, (o), (v))
 #define bcm43xx_pci_write_config16(bcm, o, v)	pci_write_config_word((bcm)->pci_dev, (o), (v))

Reply via email to