SOURCES: kernel-bcm43xx-pcie-2.6_18.1.patch (NEW) - Wireless bcm43...

blaass blaass at pld-linux.org
Sun Feb 11 00:41:20 CET 2007


Author: blaass                       Date: Sat Feb 10 23:41:20 2007 GMT
Module: SOURCES                       Tag: HEAD
---- Log message:
- Wireless bcm43xx fix for PCI-E interrupts

---- Files affected:
SOURCES:
   kernel-bcm43xx-pcie-2.6_18.1.patch (NONE -> 1.1)  (NEW)

---- Diffs:

================================================================
Index: SOURCES/kernel-bcm43xx-pcie-2.6_18.1.patch
diff -u /dev/null SOURCES/kernel-bcm43xx-pcie-2.6_18.1.patch:1.1
--- /dev/null	Sun Feb 11 00:41:20 2007
+++ SOURCES/kernel-bcm43xx-pcie-2.6_18.1.patch	Sun Feb 11 00:41:15 2007
@@ -0,0 +1,335 @@
+Index: linux-2.6.18.3/drivers/net/wireless/bcm43xx/bcm43xx_main.c
+===================================================================
+--- linux-2.6.18.3.orig/drivers/net/wireless/bcm43xx/bcm43xx_main.c
++++ linux-2.6.18.3/drivers/net/wireless/bcm43xx/bcm43xx_main.c
+@@ -130,6 +130,10 @@ MODULE_PARM_DESC(fwpostfix, "Postfix for
+ 	{ PCI_VENDOR_ID_BROADCOM, 0x4301, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ 	/* Broadcom 4307 802.11b */
+ 	{ PCI_VENDOR_ID_BROADCOM, 0x4307, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
++	/* Broadcom 4311 802.11(a)/b/g */
++	{ PCI_VENDOR_ID_BROADCOM, 0x4311, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
++	/* Broadcom 4312 802.11a/b/g */
++	{ PCI_VENDOR_ID_BROADCOM, 0x4312, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ 	/* Broadcom 4318 802.11b/g */
+ 	{ PCI_VENDOR_ID_BROADCOM, 0x4318, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ 	/* Broadcom 4319 802.11a/b/g */
+@@ -2582,8 +2586,9 @@ static int bcm43xx_probe_cores(struct bc
+ 	/* fetch sb_id_hi from core information registers */
+ 	sb_id_hi = bcm43xx_read32(bcm, BCM43xx_CIR_SB_ID_HI);
+ 
+-	core_id = (sb_id_hi & 0xFFF0) >> 4;
+-	core_rev = (sb_id_hi & 0xF);
++	core_id = (sb_id_hi & 0x8FF0) >> 4;
++	core_rev = (sb_id_hi & 0x7000) >> 8;
++	core_rev |= (sb_id_hi & 0xF);
+ 	core_vendor = (sb_id_hi & 0xFFFF0000) >> 16;
+ 
+ 	/* if present, chipcommon is always core 0; read the chipid from it */
+@@ -2682,8 +2687,8 @@ static int bcm43xx_probe_cores(struct bc
+ 		sb_id_hi = bcm43xx_read32(bcm, BCM43xx_CIR_SB_ID_HI);
+ 
+ 		/* extract core_id, core_rev, core_vendor */
+-		core_id = (sb_id_hi & 0xFFF0) >> 4;
+-		core_rev = (sb_id_hi & 0xF);
++		core_id = (sb_id_hi & 0x8FF0) >> 4;
++		core_rev = (sb_id_hi & 0xF) | (sb_id_hi & 0x7000) >> 8;
+ 		core_vendor = (sb_id_hi & 0xFFFF0000) >> 16;
+ 
+ 		dprintk(KERN_INFO PFX "Core %d: ID 0x%x, rev 0x%x, vendor 0x%x, %s\n",
+@@ -2693,6 +2698,7 @@ static int bcm43xx_probe_cores(struct bc
+ 		core = NULL;
+ 		switch (core_id) {
+ 		case BCM43xx_COREID_PCI:
++		case BCM43xx_COREID_PCIE:
+ 			core = &bcm->core_pci;
+ 			if (core->available) {
+ 				printk(KERN_WARNING PFX "Multiple PCI cores found.\n");
+@@ -2731,12 +2737,12 @@ static int bcm43xx_probe_cores(struct bc
+ 			case 6:
+ 			case 7:
+ 			case 9:
++			case 10:
+ 				break;
+ 			default:
+-				printk(KERN_ERR PFX "Error: Unsupported 80211 core revision %u\n",
++				printk(KERN_WARNING PFX
++				       "Unsupported 80211 core revision %u\n",
+ 				       core_rev);
+-				err = -ENODEV;
+-				goto out;
+ 			}
+ 			bcm->nr_80211_available++;
+ 			core->priv = ext_80211;
+@@ -2850,16 +2856,11 @@ static int bcm43xx_wireless_core_init(st
+ 	u32 sbimconfiglow;
+ 	u8 limit;
+ 
+-	if (bcm->chip_rev < 5) {
++	if (bcm->core_pci.rev <= 5 && bcm->core_pci.id != BCM43xx_COREID_PCIE) {
+ 		sbimconfiglow = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMCONFIGLOW);
+ 		sbimconfiglow &= ~ BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK;
+ 		sbimconfiglow &= ~ BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK;
+-		if (bcm->bustype == BCM43xx_BUSTYPE_PCI)
+-			sbimconfiglow |= 0x32;
+-		else if (bcm->bustype == BCM43xx_BUSTYPE_SB)
+-			sbimconfiglow |= 0x53;
+-		else
+-			assert(0);
++		sbimconfiglow |= 0x32;
+ 		bcm43xx_write32(bcm, BCM43xx_CIR_SBIMCONFIGLOW, sbimconfiglow);
+ 	}
+ 
+@@ -2983,22 +2984,64 @@ static void bcm43xx_pcicore_broadcast_va
+ 
+ static int bcm43xx_pcicore_commit_settings(struct bcm43xx_private *bcm)
+ {
+-	int err;
+-	struct bcm43xx_coreinfo *old_core;
++	int err = 0;
+ 
+-	old_core = bcm->current_core;
+-	err = bcm43xx_switch_core(bcm, &bcm->core_pci);
+-	if (err)
+-		goto out;
++	bcm->irq_savedstate = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
+ 
+-	bcm43xx_pcicore_broadcast_value(bcm, 0xfd8, 0x00000000);
++	if (bcm->core_chipcommon.available) {
++		err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
++		if (err)
++			goto out;
++
++		bcm43xx_pcicore_broadcast_value(bcm, 0xfd8, 0x00000000);
++
++		/* this function is always called when a PCI core is mapped */
++		err = bcm43xx_switch_core(bcm, &bcm->core_pci);
++		if (err)
++			goto out;
++	} else
++		bcm43xx_pcicore_broadcast_value(bcm, 0xfd8, 0x00000000);
++
++	bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate);
+ 
+-	bcm43xx_switch_core(bcm, old_core);
+-	assert(err == 0);
+ out:
+ 	return err;
+ }
+ 
++static u32 bcm43xx_pcie_reg_read(struct bcm43xx_private *bcm, u32 address)
++{
++	bcm43xx_write32(bcm, BCM43xx_PCIECORE_REG_ADDR, address);
++	return bcm43xx_read32(bcm, BCM43xx_PCIECORE_REG_DATA);
++}
++
++static void bcm43xx_pcie_reg_write(struct bcm43xx_private *bcm, u32 address,
++				    u32 data)
++{
++	bcm43xx_write32(bcm, BCM43xx_PCIECORE_REG_ADDR, address);
++	bcm43xx_write32(bcm, BCM43xx_PCIECORE_REG_DATA, data);
++}
++
++static void bcm43xx_pcie_mdio_write(struct bcm43xx_private *bcm, u8 dev, u8 reg,
++				    u16 data)
++{
++	int i;
++
++	bcm43xx_write32(bcm, BCM43xx_PCIECORE_MDIO_CTL, 0x0082);
++	bcm43xx_write32(bcm, BCM43xx_PCIECORE_MDIO_DATA, BCM43xx_PCIE_MDIO_ST |
++			BCM43xx_PCIE_MDIO_WT | (dev << BCM43xx_PCIE_MDIO_DEV) |
++			(reg << BCM43xx_PCIE_MDIO_REG) | BCM43xx_PCIE_MDIO_TA |
++			data);
++	udelay(10);
++
++	for (i = 0; i < 10; i++) {
++		if (bcm43xx_read32(bcm, BCM43xx_PCIECORE_MDIO_CTL) &
++		    BCM43xx_PCIE_MDIO_TC)
++			break;
++		msleep(1);
++	}
++	bcm43xx_write32(bcm, BCM43xx_PCIECORE_MDIO_CTL, 0);
++}
++
+ /* Make an I/O Core usable. "core_mask" is the bitmask of the cores to enable.
+  * To enable core 0, pass a core_mask of 1<<0
+  */
+@@ -3018,7 +3061,8 @@ static int bcm43xx_setup_backplane_pci_c
+ 	if (err)
+ 		goto out;
+ 
+-	if (bcm->core_pci.rev < 6) {
++	if (bcm->current_core->rev < 6 &&
++		bcm->current_core->id == BCM43xx_COREID_PCI) {
+ 		value = bcm43xx_read32(bcm, BCM43xx_CIR_SBINTVEC);
+ 		value |= (1 << backplane_flag_nr);
+ 		bcm43xx_write32(bcm, BCM43xx_CIR_SBINTVEC, value);
+@@ -3036,21 +3080,46 @@ static int bcm43xx_setup_backplane_pci_c
+ 		}
+ 	}
+ 
+-	value = bcm43xx_read32(bcm, BCM43xx_PCICORE_SBTOPCI2);
+-	value |= BCM43xx_SBTOPCI2_PREFETCH | BCM43xx_SBTOPCI2_BURST;
+-	bcm43xx_write32(bcm, BCM43xx_PCICORE_SBTOPCI2, value);
+-
+-	if (bcm->core_pci.rev < 5) {
+-		value = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMCONFIGLOW);
+-		value |= (2 << BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_SHIFT)
+-			 & BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK;
+-		value |= (3 << BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_SHIFT)
+-			 & BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK;
+-		bcm43xx_write32(bcm, BCM43xx_CIR_SBIMCONFIGLOW, value);
+-		err = bcm43xx_pcicore_commit_settings(bcm);
+-		assert(err == 0);
++	if (bcm->current_core->id == BCM43xx_COREID_PCI) {
++		value = bcm43xx_read32(bcm, BCM43xx_PCICORE_SBTOPCI2);
++		value |= BCM43xx_SBTOPCI2_PREFETCH | BCM43xx_SBTOPCI2_BURST;
++		bcm43xx_write32(bcm, BCM43xx_PCICORE_SBTOPCI2, value);
++
++		if (bcm->current_core->rev < 5) {
++			value = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMCONFIGLOW);
++			value |= (2 << BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_SHIFT)
++				 & BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK;
++			value |= (3 << BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_SHIFT)
++				 & BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK;
++			bcm43xx_write32(bcm, BCM43xx_CIR_SBIMCONFIGLOW, value);
++			err = bcm43xx_pcicore_commit_settings(bcm);
++			assert(err == 0);
++		} else if (bcm->current_core->rev >= 11) {
++			value = bcm43xx_read32(bcm, BCM43xx_PCICORE_SBTOPCI2);
++			value |= BCM43xx_SBTOPCI2_MEMREAD_MULTI;
++			bcm43xx_write32(bcm, BCM43xx_PCICORE_SBTOPCI2, value);
++		}
++	} else {
++		if (bcm->current_core->rev == 0 || bcm->current_core->rev == 1) {
++			value = bcm43xx_pcie_reg_read(bcm, BCM43xx_PCIE_TLP_WORKAROUND);
++			value |= 0x8;
++			bcm43xx_pcie_reg_write(bcm, BCM43xx_PCIE_TLP_WORKAROUND,
++					       value);
++		}
++		if (bcm->current_core->rev == 0) {
++			bcm43xx_pcie_mdio_write(bcm, BCM43xx_MDIO_SERDES_RX,
++						BCM43xx_SERDES_RXTIMER, 0x8128);
++			bcm43xx_pcie_mdio_write(bcm, BCM43xx_MDIO_SERDES_RX,
++						BCM43xx_SERDES_CDR, 0x0100);
++			bcm43xx_pcie_mdio_write(bcm, BCM43xx_MDIO_SERDES_RX,
++						BCM43xx_SERDES_CDR_BW, 0x1466);
++		} else if (bcm->current_core->rev == 1) {
++			value = bcm43xx_pcie_reg_read(bcm, BCM43xx_PCIE_DLLP_LINKCTL);
++			value |= 0x40;
++			bcm43xx_pcie_reg_write(bcm, BCM43xx_PCIE_DLLP_LINKCTL,
++					       value);
++		}
+ 	}
+-
+ out_switch_back:
+ 	err = bcm43xx_switch_core(bcm, old_core);
+ out:
+@@ -3643,7 +3712,7 @@ static int bcm43xx_read_phyinfo(struct b
+ 		bcm->ieee->freq_band = IEEE80211_24GHZ_BAND;
+ 		break;
+ 	case BCM43xx_PHYTYPE_G:
+-		if (phy_rev > 7)
++		if (phy_rev > 8)
+ 			phy_rev_ok = 0;
+ 		bcm->ieee->modulation = IEEE80211_OFDM_MODULATION |
+ 					IEEE80211_CCK_MODULATION;
+Index: linux-2.6.18.3/drivers/net/wireless/bcm43xx/bcm43xx.h
+===================================================================
+--- linux-2.6.18.3.orig/drivers/net/wireless/bcm43xx/bcm43xx.h
++++ linux-2.6.18.3/drivers/net/wireless/bcm43xx/bcm43xx.h
+@@ -159,6 +159,7 @@
+ 
+ /* Chipcommon registers. */
+ #define BCM43xx_CHIPCOMMON_CAPABILITIES 	0x04
++#define BCM43xx_CHIPCOMMON_CTL			0x28
+ #define BCM43xx_CHIPCOMMON_PLLONDELAY		0xB0
+ #define BCM43xx_CHIPCOMMON_FREFSELDELAY		0xB4
+ #define BCM43xx_CHIPCOMMON_SLOWCLKCTL		0xB8
+@@ -172,6 +173,33 @@
+ /* SBTOPCI2 values. */
+ #define BCM43xx_SBTOPCI2_PREFETCH	0x4
+ #define BCM43xx_SBTOPCI2_BURST		0x8
++#define BCM43xx_SBTOPCI2_MEMREAD_MULTI	0x20
++
++/* PCI-E core registers. */
++#define BCM43xx_PCIECORE_REG_ADDR      0x0130
++#define BCM43xx_PCIECORE_REG_DATA      0x0134
++#define BCM43xx_PCIECORE_MDIO_CTL      0x0128
++#define BCM43xx_PCIECORE_MDIO_DATA     0x012C
++
++/* PCI-E registers. */
++#define BCM43xx_PCIE_TLP_WORKAROUND    0x0004
++#define BCM43xx_PCIE_DLLP_LINKCTL      0x0100
++
++/* PCI-E MDIO bits. */
++#define BCM43xx_PCIE_MDIO_ST   0x40000000
++#define BCM43xx_PCIE_MDIO_WT   0x10000000
++#define BCM43xx_PCIE_MDIO_DEV  22
++#define BCM43xx_PCIE_MDIO_REG  18
++#define BCM43xx_PCIE_MDIO_TA   0x00020000
++#define BCM43xx_PCIE_MDIO_TC   0x0100
++
++/* MDIO devices. */
++#define BCM43xx_MDIO_SERDES_RX	0x1F
++
++/* SERDES RX registers. */
++#define BCM43xx_SERDES_RXTIMER	0x2
++#define BCM43xx_SERDES_CDR	0x6
++#define BCM43xx_SERDES_CDR_BW	0x7
+ 
+ /* Chipcommon capabilities. */
+ #define BCM43xx_CAPABILITIES_PCTL		0x00040000
+@@ -221,6 +249,7 @@
+ #define BCM43xx_COREID_USB20_HOST       0x819
+ #define BCM43xx_COREID_USB20_DEV        0x81a
+ #define BCM43xx_COREID_SDIO_HOST        0x81b
++#define BCM43xx_COREID_PCIE		0x820
+ 
+ /* Core Information Registers */
+ #define BCM43xx_CIR_BASE		0xf00
+Index: linux-2.6.18.3/drivers/net/wireless/bcm43xx/bcm43xx_power.c
+===================================================================
+--- linux-2.6.18.3.orig/drivers/net/wireless/bcm43xx/bcm43xx_power.c
++++ linux-2.6.18.3/drivers/net/wireless/bcm43xx/bcm43xx_power.c
+@@ -153,8 +153,6 @@ int bcm43xx_pctl_init(struct bcm43xx_pri
+ 	int err, maxfreq;
+ 	struct bcm43xx_coreinfo *old_core;
+ 
+-	if (!(bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL))
+-		return 0;
+ 	old_core = bcm->current_core;
+ 	err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
+ 	if (err == -ENODEV)
+@@ -162,11 +160,27 @@ int bcm43xx_pctl_init(struct bcm43xx_pri
+ 	if (err)
+ 		goto out;
+ 
+-	maxfreq = bcm43xx_pctl_clockfreqlimit(bcm, 1);
+-	bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_PLLONDELAY,
+-			(maxfreq * 150 + 999999) / 1000000);
+-	bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_FREFSELDELAY,
+-			(maxfreq * 15 + 999999) / 1000000);
++	if (bcm->chip_id == 0x4321) {
++		if (bcm->chip_rev == 0)
++			bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_CTL, 0x03A4);
++		if (bcm->chip_rev == 1)
++			bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_CTL, 0x00A4);
++	}
++
++	if (bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL) {
++		if (bcm->current_core->rev >= 10) {
++			/* Set Idle Power clock rate to 1Mhz */
++			bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_SYSCLKCTL,
++				       (bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SYSCLKCTL)
++				       & 0x0000FFFF) | 0x40000);
++		} else {
++			maxfreq = bcm43xx_pctl_clockfreqlimit(bcm, 1);
++			bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_PLLONDELAY,
++				       (maxfreq * 150 + 999999) / 1000000);
++			bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_FREFSELDELAY,
++				       (maxfreq * 15 + 999999) / 1000000);
++		}
++	}
+ 
+ 	err = bcm43xx_switch_core(bcm, old_core);
+ 	assert(err == 0);
================================================================


More information about the pld-cvs-commit mailing list