diff options
Diffstat (limited to 'target/linux/generic/patches-2.6.32/975-ssb_update.patch')
| -rw-r--r-- | target/linux/generic/patches-2.6.32/975-ssb_update.patch | 565 | 
1 files changed, 552 insertions, 13 deletions
diff --git a/target/linux/generic/patches-2.6.32/975-ssb_update.patch b/target/linux/generic/patches-2.6.32/975-ssb_update.patch index 373df1a62..a2cb4472e 100644 --- a/target/linux/generic/patches-2.6.32/975-ssb_update.patch +++ b/target/linux/generic/patches-2.6.32/975-ssb_update.patch @@ -1,6 +1,44 @@  --- a/drivers/ssb/driver_chipcommon.c  +++ b/drivers/ssb/driver_chipcommon.c -@@ -373,6 +373,7 @@ u32 ssb_chipco_gpio_control(struct ssb_c +@@ -209,6 +209,24 @@ static void chipco_powercontrol_init(str + 	} + } +  ++/* http://bcm-v4.sipsolutions.net/802.11/PmuFastPwrupDelay */ ++static u16 pmu_fast_powerup_delay(struct ssb_chipcommon *cc) ++{ ++	struct ssb_bus *bus = cc->dev->bus; ++ ++	switch (bus->chip_id) { ++	case 0x4312: ++	case 0x4322: ++	case 0x4328: ++		return 7000; ++	case 0x4325: ++		/* TODO: */ ++	default: ++		return 15000; ++	} ++} ++ ++/* http://bcm-v4.sipsolutions.net/802.11/ClkctlFastPwrupDelay */ + static void calc_fast_powerup_delay(struct ssb_chipcommon *cc) + { + 	struct ssb_bus *bus = cc->dev->bus; +@@ -218,6 +236,12 @@ static void calc_fast_powerup_delay(stru +  + 	if (bus->bustype != SSB_BUSTYPE_PCI) + 		return; ++ ++	if (cc->capabilities & SSB_CHIPCO_CAP_PMU) { ++		cc->fast_pwrup_delay = pmu_fast_powerup_delay(cc); ++		return; ++	} ++ + 	if (!(cc->capabilities & SSB_CHIPCO_CAP_PCTL)) + 		return; +  +@@ -373,6 +397,7 @@ u32 ssb_chipco_gpio_control(struct ssb_c   {   	return chipco_write32_masked(cc, SSB_CHIPCO_GPIOCTL, mask, value);   } @@ -31,6 +69,39 @@   		/* We keep the default settings:   		 * min_msk = 0xCBB   		 * max_msk = 0x7FFFF +@@ -495,9 +502,9 @@ static void ssb_pmu_resources_init(struc + 		chipco_write32(cc, SSB_CHIPCO_PMU_MAXRES_MSK, max_msk); + } +  ++/* http://bcm-v4.sipsolutions.net/802.11/SSB/PmuInit */ + void ssb_pmu_init(struct ssb_chipcommon *cc) + { +-	struct ssb_bus *bus = cc->dev->bus; + 	u32 pmucap; +  + 	if (!(cc->capabilities & SSB_CHIPCO_CAP_PMU)) +@@ -509,15 +516,12 @@ void ssb_pmu_init(struct ssb_chipcommon + 	ssb_dprintk(KERN_DEBUG PFX "Found rev %u PMU (capabilities 0x%08X)\n", + 		    cc->pmu.rev, pmucap); +  +-	if (cc->pmu.rev >= 1) { +-		if ((bus->chip_id == 0x4325) && (bus->chip_rev < 2)) { +-			chipco_mask32(cc, SSB_CHIPCO_PMU_CTL, +-				      ~SSB_CHIPCO_PMU_CTL_NOILPONW); +-		} else { +-			chipco_set32(cc, SSB_CHIPCO_PMU_CTL, +-				     SSB_CHIPCO_PMU_CTL_NOILPONW); +-		} +-	} ++	if (cc->pmu.rev == 1) ++		chipco_mask32(cc, SSB_CHIPCO_PMU_CTL, ++			      ~SSB_CHIPCO_PMU_CTL_NOILPONW); ++	else ++		chipco_set32(cc, SSB_CHIPCO_PMU_CTL, ++			     SSB_CHIPCO_PMU_CTL_NOILPONW); + 	ssb_pmu_pll_init(cc); + 	ssb_pmu_resources_init(cc); + }  --- a/drivers/ssb/driver_gige.c  +++ b/drivers/ssb/driver_gige.c  @@ -12,6 +12,7 @@ @@ -214,13 +285,13 @@  -		if (!dev->dev ||  -		    !dev->dev->driver ||  -		    !device_is_registered(dev->dev)) +-			continue; +-		drv = drv_to_ssb_drv(dev->dev->driver); +-		if (!drv)  +		sdrv = ssb_driver_get(drv_to_ssb_drv(sdev->dev->driver));  +		if (!sdrv || SSB_WARN_ON(!sdrv->remove)) {  +			ssb_device_put(sdev);   			continue; --		drv = drv_to_ssb_drv(dev->dev->driver); --		if (!drv) --			continue;  -		err = drv->suspend(dev, state);  -		if (err) {  -			ssb_printk(KERN_ERR PFX "Failed to freeze device %s\n", @@ -302,7 +373,59 @@   }   #endif /* CONFIG_SSB_SPROM */ -@@ -490,8 +495,7 @@ static int ssb_devices_register(struct s +@@ -380,6 +385,35 @@ static int ssb_device_uevent(struct devi + 			     ssb_dev->id.revision); + } +  ++#define ssb_config_attr(attrib, field, format_string) \ ++static ssize_t \ ++attrib##_show(struct device *dev, struct device_attribute *attr, char *buf) \ ++{ \ ++	return sprintf(buf, format_string, dev_to_ssb_dev(dev)->field); \ ++} ++ ++ssb_config_attr(core_num, core_index, "%u\n") ++ssb_config_attr(coreid, id.coreid, "0x%04x\n") ++ssb_config_attr(vendor, id.vendor, "0x%04x\n") ++ssb_config_attr(revision, id.revision, "%u\n") ++ssb_config_attr(irq, irq, "%u\n") ++static ssize_t ++name_show(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++	return sprintf(buf, "%s\n", ++		       ssb_core_name(dev_to_ssb_dev(dev)->id.coreid)); ++} ++ ++static struct device_attribute ssb_device_attrs[] = { ++	__ATTR_RO(name), ++	__ATTR_RO(core_num), ++	__ATTR_RO(coreid), ++	__ATTR_RO(vendor), ++	__ATTR_RO(revision), ++	__ATTR_RO(irq), ++	__ATTR_NULL, ++}; ++ + static struct bus_type ssb_bustype = { + 	.name		= "ssb", + 	.match		= ssb_bus_match, +@@ -389,6 +423,7 @@ static struct bus_type ssb_bustype = { + 	.suspend	= ssb_device_suspend, + 	.resume		= ssb_device_resume, + 	.uevent		= ssb_device_uevent, ++	.dev_attrs	= ssb_device_attrs, + }; +  + static void ssb_buses_lock(void) +@@ -481,6 +516,7 @@ static int ssb_devices_register(struct s + #ifdef CONFIG_SSB_PCIHOST + 			sdev->irq = bus->host_pci->irq; + 			dev->parent = &bus->host_pci->dev; ++			sdev->dma_dev = dev->parent; + #endif + 			break; + 		case SSB_BUSTYPE_PCMCIA: +@@ -490,13 +526,13 @@ static int ssb_devices_register(struct s   #endif   			break;   		case SSB_BUSTYPE_SDIO: @@ -312,7 +435,13 @@   			dev->parent = &bus->host_sdio->dev;   #endif   			break; -@@ -830,6 +834,9 @@ int ssb_bus_pcibus_register(struct ssb_b + 		case SSB_BUSTYPE_SSB: + 			dev->dma_mask = &dev->coherent_dma_mask; ++			sdev->dma_dev = dev; + 			break; + 		} +  +@@ -830,6 +866,9 @@ int ssb_bus_pcibus_register(struct ssb_b   	if (!err) {   		ssb_printk(KERN_INFO PFX "Sonics Silicon Backplane found on "   			   "PCI device %s\n", dev_name(&host_pci->dev)); @@ -322,6 +451,270 @@   	}   	return err; +@@ -1155,10 +1194,10 @@ void ssb_device_enable(struct ssb_device + } + EXPORT_SYMBOL(ssb_device_enable); +  +-/* Wait for a bit in a register to get set or unset. ++/* Wait for bitmask in a register to get set or cleared. +  * timeout is in units of ten-microseconds */ +-static int ssb_wait_bit(struct ssb_device *dev, u16 reg, u32 bitmask, +-			int timeout, int set) ++static int ssb_wait_bits(struct ssb_device *dev, u16 reg, u32 bitmask, ++			 int timeout, int set) + { + 	int i; + 	u32 val; +@@ -1166,7 +1205,7 @@ static int ssb_wait_bit(struct ssb_devic + 	for (i = 0; i < timeout; i++) { + 		val = ssb_read32(dev, reg); + 		if (set) { +-			if (val & bitmask) ++			if ((val & bitmask) == bitmask) + 				return 0; + 		} else { + 			if (!(val & bitmask)) +@@ -1183,20 +1222,38 @@ static int ssb_wait_bit(struct ssb_devic +  + void ssb_device_disable(struct ssb_device *dev, u32 core_specific_flags) + { +-	u32 reject; ++	u32 reject, val; +  + 	if (ssb_read32(dev, SSB_TMSLOW) & SSB_TMSLOW_RESET) + 		return; +  + 	reject = ssb_tmslow_reject_bitmask(dev); +-	ssb_write32(dev, SSB_TMSLOW, reject | SSB_TMSLOW_CLOCK); +-	ssb_wait_bit(dev, SSB_TMSLOW, reject, 1000, 1); +-	ssb_wait_bit(dev, SSB_TMSHIGH, SSB_TMSHIGH_BUSY, 1000, 0); +-	ssb_write32(dev, SSB_TMSLOW, +-		    SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK | +-		    reject | SSB_TMSLOW_RESET | +-		    core_specific_flags); +-	ssb_flush_tmslow(dev); ++ ++	if (ssb_read32(dev, SSB_TMSLOW) & SSB_TMSLOW_CLOCK) { ++		ssb_write32(dev, SSB_TMSLOW, reject | SSB_TMSLOW_CLOCK); ++		ssb_wait_bits(dev, SSB_TMSLOW, reject, 1000, 1); ++		ssb_wait_bits(dev, SSB_TMSHIGH, SSB_TMSHIGH_BUSY, 1000, 0); ++ ++		if (ssb_read32(dev, SSB_IDLOW) & SSB_IDLOW_INITIATOR) { ++			val = ssb_read32(dev, SSB_IMSTATE); ++			val |= SSB_IMSTATE_REJECT; ++			ssb_write32(dev, SSB_IMSTATE, val); ++			ssb_wait_bits(dev, SSB_IMSTATE, SSB_IMSTATE_BUSY, 1000, ++				      0); ++		} ++ ++		ssb_write32(dev, SSB_TMSLOW, ++			SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK | ++			reject | SSB_TMSLOW_RESET | ++			core_specific_flags); ++		ssb_flush_tmslow(dev); ++ ++		if (ssb_read32(dev, SSB_IDLOW) & SSB_IDLOW_INITIATOR) { ++			val = ssb_read32(dev, SSB_IMSTATE); ++			val &= ~SSB_IMSTATE_REJECT; ++			ssb_write32(dev, SSB_IMSTATE, val); ++		} ++	} +  + 	ssb_write32(dev, SSB_TMSLOW, + 		    reject | SSB_TMSLOW_RESET | +--- a/drivers/ssb/pci.c ++++ b/drivers/ssb/pci.c +@@ -17,6 +17,7 @@ +  + #include <linux/ssb/ssb.h> + #include <linux/ssb/ssb_regs.h> ++#include <linux/slab.h> + #include <linux/pci.h> + #include <linux/delay.h> +  +@@ -167,7 +168,7 @@ err_pci: + } +  + /* Get the word-offset for a SSB_SPROM_XXX define. */ +-#define SPOFF(offset)	(((offset) - SSB_SPROM_BASE1) / sizeof(u16)) ++#define SPOFF(offset)	((offset) / sizeof(u16)) + /* Helper to extract some _offset, which is one of the SSB_SPROM_XXX defines. */ + #define SPEX16(_outvar, _offset, _mask, _shift)	\ + 	out->_outvar = ((in[SPOFF(_offset)] & (_mask)) >> (_shift)) +@@ -405,6 +406,46 @@ static void sprom_extract_r123(struct ss + 	out->antenna_gain.ghz5.a3 = gain; + } +  ++/* Revs 4 5 and 8 have partially shared layout */ ++static void sprom_extract_r458(struct ssb_sprom *out, const u16 *in) ++{ ++	SPEX(txpid2g[0], SSB_SPROM4_TXPID2G01, ++	     SSB_SPROM4_TXPID2G0, SSB_SPROM4_TXPID2G0_SHIFT); ++	SPEX(txpid2g[1], SSB_SPROM4_TXPID2G01, ++	     SSB_SPROM4_TXPID2G1, SSB_SPROM4_TXPID2G1_SHIFT); ++	SPEX(txpid2g[2], SSB_SPROM4_TXPID2G23, ++	     SSB_SPROM4_TXPID2G2, SSB_SPROM4_TXPID2G2_SHIFT); ++	SPEX(txpid2g[3], SSB_SPROM4_TXPID2G23, ++	     SSB_SPROM4_TXPID2G3, SSB_SPROM4_TXPID2G3_SHIFT); ++ ++	SPEX(txpid5gl[0], SSB_SPROM4_TXPID5GL01, ++	     SSB_SPROM4_TXPID5GL0, SSB_SPROM4_TXPID5GL0_SHIFT); ++	SPEX(txpid5gl[1], SSB_SPROM4_TXPID5GL01, ++	     SSB_SPROM4_TXPID5GL1, SSB_SPROM4_TXPID5GL1_SHIFT); ++	SPEX(txpid5gl[2], SSB_SPROM4_TXPID5GL23, ++	     SSB_SPROM4_TXPID5GL2, SSB_SPROM4_TXPID5GL2_SHIFT); ++	SPEX(txpid5gl[3], SSB_SPROM4_TXPID5GL23, ++	     SSB_SPROM4_TXPID5GL3, SSB_SPROM4_TXPID5GL3_SHIFT); ++ ++	SPEX(txpid5g[0], SSB_SPROM4_TXPID5G01, ++	     SSB_SPROM4_TXPID5G0, SSB_SPROM4_TXPID5G0_SHIFT); ++	SPEX(txpid5g[1], SSB_SPROM4_TXPID5G01, ++	     SSB_SPROM4_TXPID5G1, SSB_SPROM4_TXPID5G1_SHIFT); ++	SPEX(txpid5g[2], SSB_SPROM4_TXPID5G23, ++	     SSB_SPROM4_TXPID5G2, SSB_SPROM4_TXPID5G2_SHIFT); ++	SPEX(txpid5g[3], SSB_SPROM4_TXPID5G23, ++	     SSB_SPROM4_TXPID5G3, SSB_SPROM4_TXPID5G3_SHIFT); ++ ++	SPEX(txpid5gh[0], SSB_SPROM4_TXPID5GH01, ++	     SSB_SPROM4_TXPID5GH0, SSB_SPROM4_TXPID5GH0_SHIFT); ++	SPEX(txpid5gh[1], SSB_SPROM4_TXPID5GH01, ++	     SSB_SPROM4_TXPID5GH1, SSB_SPROM4_TXPID5GH1_SHIFT); ++	SPEX(txpid5gh[2], SSB_SPROM4_TXPID5GH23, ++	     SSB_SPROM4_TXPID5GH2, SSB_SPROM4_TXPID5GH2_SHIFT); ++	SPEX(txpid5gh[3], SSB_SPROM4_TXPID5GH23, ++	     SSB_SPROM4_TXPID5GH3, SSB_SPROM4_TXPID5GH3_SHIFT); ++} ++ + static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in) + { + 	int i; +@@ -427,10 +468,14 @@ static void sprom_extract_r45(struct ssb + 		SPEX(country_code, SSB_SPROM4_CCODE, 0xFFFF, 0); + 		SPEX(boardflags_lo, SSB_SPROM4_BFLLO, 0xFFFF, 0); + 		SPEX(boardflags_hi, SSB_SPROM4_BFLHI, 0xFFFF, 0); ++		SPEX(boardflags2_lo, SSB_SPROM4_BFL2LO, 0xFFFF, 0); ++		SPEX(boardflags2_hi, SSB_SPROM4_BFL2HI, 0xFFFF, 0); + 	} else { + 		SPEX(country_code, SSB_SPROM5_CCODE, 0xFFFF, 0); + 		SPEX(boardflags_lo, SSB_SPROM5_BFLLO, 0xFFFF, 0); + 		SPEX(boardflags_hi, SSB_SPROM5_BFLHI, 0xFFFF, 0); ++		SPEX(boardflags2_lo, SSB_SPROM5_BFL2LO, 0xFFFF, 0); ++		SPEX(boardflags2_hi, SSB_SPROM5_BFL2HI, 0xFFFF, 0); + 	} + 	SPEX(ant_available_a, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_A, + 	     SSB_SPROM4_ANTAVAIL_A_SHIFT); +@@ -470,6 +515,8 @@ static void sprom_extract_r45(struct ssb + 	memcpy(&out->antenna_gain.ghz5, &out->antenna_gain.ghz24, + 	       sizeof(out->antenna_gain.ghz5)); +  ++	sprom_extract_r458(out, in); ++ + 	/* TODO - get remaining rev 4 stuff needed */ + } +  +@@ -560,6 +607,8 @@ static void sprom_extract_r8(struct ssb_ + 	memcpy(&out->antenna_gain.ghz5, &out->antenna_gain.ghz24, + 	       sizeof(out->antenna_gain.ghz5)); +  ++	sprom_extract_r458(out, in); ++ + 	/* TODO - get remaining rev 8 stuff needed */ + } +  +@@ -572,37 +621,34 @@ static int sprom_extract(struct ssb_bus + 	ssb_dprintk(KERN_DEBUG PFX "SPROM revision %d detected.\n", out->revision); + 	memset(out->et0mac, 0xFF, 6);		/* preset et0 and et1 mac */ + 	memset(out->et1mac, 0xFF, 6); ++ + 	if ((bus->chip_id & 0xFF00) == 0x4400) { + 		/* Workaround: The BCM44XX chip has a stupid revision + 		 * number stored in the SPROM. + 		 * Always extract r1. */ + 		out->revision = 1; ++		ssb_dprintk(KERN_DEBUG PFX "SPROM treated as revision %d\n", out->revision); ++	} ++ ++	switch (out->revision) { ++	case 1: ++	case 2: ++	case 3: + 		sprom_extract_r123(out, in); +-	} else if (bus->chip_id == 0x4321) { +-		/* the BCM4328 has a chipid == 0x4321 and a rev 4 SPROM */ +-		out->revision = 4; ++		break; ++	case 4: ++	case 5: + 		sprom_extract_r45(out, in); +-	} else { +-		switch (out->revision) { +-		case 1: +-		case 2: +-		case 3: +-			sprom_extract_r123(out, in); +-			break; +-		case 4: +-		case 5: +-			sprom_extract_r45(out, in); +-			break; +-		case 8: +-			sprom_extract_r8(out, in); +-			break; +-		default: +-			ssb_printk(KERN_WARNING PFX "Unsupported SPROM" +-				   "  revision %d detected. Will extract" +-				   " v1\n", out->revision); +-			out->revision = 1; +-			sprom_extract_r123(out, in); +-		} ++		break; ++	case 8: ++		sprom_extract_r8(out, in); ++		break; ++	default: ++		ssb_printk(KERN_WARNING PFX "Unsupported SPROM" ++			   " revision %d detected. Will extract" ++			   " v1\n", out->revision); ++		out->revision = 1; ++		sprom_extract_r123(out, in); + 	} +  + 	if (out->boardflags_lo == 0xFFFF) +@@ -617,7 +663,7 @@ static int ssb_pci_sprom_get(struct ssb_ + 			     struct ssb_sprom *sprom) + { + 	const struct ssb_sprom *fallback; +-	int err = -ENOMEM; ++	int err; + 	u16 *buf; +  + 	if (!ssb_is_sprom_available(bus)) { +@@ -644,7 +690,7 @@ static int ssb_pci_sprom_get(struct ssb_ +  + 	buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL); + 	if (!buf) +-		goto out; ++		return -ENOMEM; + 	bus->sprom_size = SSB_SPROMSIZE_WORDS_R123; + 	sprom_do_read(bus, buf); + 	err = sprom_check_crc(buf, bus->sprom_size); +@@ -654,7 +700,7 @@ static int ssb_pci_sprom_get(struct ssb_ + 		buf = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16), + 			      GFP_KERNEL); + 		if (!buf) +-			goto out; ++			return -ENOMEM; + 		bus->sprom_size = SSB_SPROMSIZE_WORDS_R4; + 		sprom_do_read(bus, buf); + 		err = sprom_check_crc(buf, bus->sprom_size); +@@ -676,7 +722,6 @@ static int ssb_pci_sprom_get(struct ssb_ +  + out_free: + 	kfree(buf); +-out: + 	return err; + } +   --- a/drivers/ssb/pcihost_wrapper.c  +++ b/drivers/ssb/pcihost_wrapper.c  @@ -12,6 +12,7 @@ @@ -332,6 +725,27 @@   #include <linux/ssb/ssb.h> +@@ -58,6 +59,7 @@ static int ssb_pcihost_probe(struct pci_ + 	struct ssb_bus *ssb; + 	int err = -ENOMEM; + 	const char *name; ++	u32 val; +  + 	ssb = kzalloc(sizeof(*ssb), GFP_KERNEL); + 	if (!ssb) +@@ -73,6 +75,12 @@ static int ssb_pcihost_probe(struct pci_ + 		goto err_pci_disable; + 	pci_set_master(dev); +  ++	/* Disable the RETRY_TIMEOUT register (0x41) to keep ++	 * PCI Tx retries from interfering with C3 CPU state */ ++	pci_read_config_dword(dev, 0x40, &val); ++	if ((val & 0x0000ff00) != 0) ++		pci_write_config_dword(dev, 0x40, val & 0xffff00ff); ++ + 	err = ssb_bus_pcibus_register(ssb, dev); + 	if (err) + 		goto err_pci_release_regions;  --- a/drivers/ssb/pcmcia.c  +++ b/drivers/ssb/pcmcia.c  @@ -617,136 +617,140 @@ static int ssb_pcmcia_sprom_check_crc(co @@ -576,7 +990,7 @@  -		GOTO_ERROR_ON(res != 0, "VEN next tpl data");  -	}  +	res = pcmcia_loop_tuple(bus->host_pcmcia, SSB_PCMCIA_CIS, -+				ssb_pcmcia_do_get_invariants, sprom); ++				ssb_pcmcia_do_get_invariants, iv);  +	if ((res == 0) || (res == -ENOSPC))  +		return 0; @@ -600,6 +1014,23 @@   			    "Core %d found: %s "   			    "(cc 0x%03X, rev 0x%02X, vendor 0x%04X)\n",   			    i, ssb_core_name(dev->id.coreid), +@@ -422,6 +422,16 @@ int ssb_bus_scan(struct ssb_bus *bus, + 			bus->pcicore.dev = dev; + #endif /* CONFIG_SSB_DRIVER_PCICORE */ + 			break; ++		case SSB_DEV_ETHERNET: ++			if (bus->bustype == SSB_BUSTYPE_PCI) { ++				if (bus->host_pci->vendor == PCI_VENDOR_ID_BROADCOM && ++				    (bus->host_pci->device & 0xFF00) == 0x4300) { ++					/* This is a dangling ethernet core on a ++					 * wireless device. Ignore it. */ ++					continue; ++				} ++			} ++			break; + 		default: + 			break; + 		}  --- a/drivers/ssb/sprom.c  +++ b/drivers/ssb/sprom.c  @@ -14,6 +14,7 @@ @@ -682,7 +1113,27 @@   #endif /* LINUX_SSB_PRIVATE_H_ */  --- a/include/linux/ssb/ssb.h  +++ b/include/linux/ssb/ssb.h -@@ -269,7 +269,8 @@ struct ssb_bus { +@@ -55,6 +55,10 @@ struct ssb_sprom { + 	u8 tri5gl;		/* 5.2GHz TX isolation */ + 	u8 tri5g;		/* 5.3GHz TX isolation */ + 	u8 tri5gh;		/* 5.8GHz TX isolation */ ++	u8 txpid2g[4];		/* 2GHz TX power index */ ++	u8 txpid5gl[4];		/* 4.9 - 5.1GHz TX power index */ ++	u8 txpid5g[4];		/* 5.1 - 5.5GHz TX power index */ ++	u8 txpid5gh[4];		/* 5.5 - ...GHz TX power index */ + 	u8 rxpo2g;		/* 2GHz RX power offset */ + 	u8 rxpo5g;		/* 5GHz RX power offset */ + 	u8 rssisav2g;		/* 2GHz RSSI params */ +@@ -167,7 +171,7 @@ struct ssb_device { + 	 * is an optimization. */ + 	const struct ssb_bus_ops *ops; +  +-	struct device *dev; ++	struct device *dev, *dma_dev; +  + 	struct ssb_bus *bus; + 	struct ssb_device_id id; +@@ -269,7 +273,8 @@ struct ssb_bus {   	const struct ssb_bus_ops *ops; @@ -692,7 +1143,7 @@   	struct ssb_device *mapped_device;   	union {   		/* Currently mapped PCMCIA segment. (bustype == SSB_BUSTYPE_PCMCIA only) */ -@@ -281,14 +282,17 @@ struct ssb_bus { +@@ -281,14 +286,17 @@ struct ssb_bus {   	 * On PCMCIA-host busses this is used to protect the whole MMIO access. */   	spinlock_t bar_lock; @@ -719,7 +1170,51 @@   	unsigned int quirks;  --- a/include/linux/ssb/ssb_regs.h  +++ b/include/linux/ssb/ssb_regs.h -@@ -198,63 +198,63 @@ +@@ -85,6 +85,8 @@ + #define  SSB_IMSTATE_AP_RSV	0x00000030 /* Reserved */ + #define  SSB_IMSTATE_IBE	0x00020000 /* In Band Error */ + #define  SSB_IMSTATE_TO		0x00040000 /* Timeout */ ++#define  SSB_IMSTATE_BUSY	0x01800000 /* Busy (Backplane rev >= 2.3 only) */ ++#define  SSB_IMSTATE_REJECT	0x02000000 /* Reject (Backplane rev >= 2.3 only) */ + #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 */ +@@ -172,25 +174,25 @@ + #define SSB_SPROMSIZE_BYTES_R4		(SSB_SPROMSIZE_WORDS_R4 * sizeof(u16)) + #define SSB_SPROM_BASE1			0x1000 + #define SSB_SPROM_BASE31		0x0800 +-#define SSB_SPROM_REVISION		0x107E ++#define SSB_SPROM_REVISION		0x007E + #define  SSB_SPROM_REVISION_REV		0x00FF	/* SPROM Revision number */ + #define  SSB_SPROM_REVISION_CRC		0xFF00	/* SPROM CRC8 value */ + #define  SSB_SPROM_REVISION_CRC_SHIFT	8 +  + /* SPROM Revision 1 */ +-#define SSB_SPROM1_SPID			0x1004	/* Subsystem Product ID for PCI */ +-#define SSB_SPROM1_SVID			0x1006	/* Subsystem Vendor ID for PCI */ +-#define SSB_SPROM1_PID			0x1008	/* Product ID for PCI */ +-#define SSB_SPROM1_IL0MAC		0x1048	/* 6 bytes MAC address for 802.11b/g */ +-#define SSB_SPROM1_ET0MAC		0x104E	/* 6 bytes MAC address for Ethernet */ +-#define SSB_SPROM1_ET1MAC		0x1054	/* 6 bytes MAC address for 802.11a */ +-#define SSB_SPROM1_ETHPHY		0x105A	/* Ethernet PHY settings */ ++#define SSB_SPROM1_SPID			0x0004	/* Subsystem Product ID for PCI */ ++#define SSB_SPROM1_SVID			0x0006	/* Subsystem Vendor ID for PCI */ ++#define SSB_SPROM1_PID			0x0008	/* Product ID for PCI */ ++#define SSB_SPROM1_IL0MAC		0x0048	/* 6 bytes MAC address for 802.11b/g */ ++#define SSB_SPROM1_ET0MAC		0x004E	/* 6 bytes MAC address for Ethernet */ ++#define SSB_SPROM1_ET1MAC		0x0054	/* 6 bytes MAC address for 802.11a */ ++#define SSB_SPROM1_ETHPHY		0x005A	/* Ethernet PHY settings */ + #define  SSB_SPROM1_ETHPHY_ET0A		0x001F	/* MII Address for enet0 */ + #define  SSB_SPROM1_ETHPHY_ET1A		0x03E0	/* MII Address for enet1 */ + #define  SSB_SPROM1_ETHPHY_ET1A_SHIFT	5 + #define  SSB_SPROM1_ETHPHY_ET0M		(1<<14)	/* MDIO for enet0 */ + #define  SSB_SPROM1_ETHPHY_ET1M		(1<<15)	/* MDIO for enet1 */ +-#define SSB_SPROM1_BINF			0x105C	/* Board info */ ++#define SSB_SPROM1_BINF			0x005C	/* Board info */ + #define  SSB_SPROM1_BINF_BREV		0x00FF	/* Board Revision */ + #define  SSB_SPROM1_BINF_CCODE		0x0F00	/* Country Code */ + #define  SSB_SPROM1_BINF_CCODE_SHIFT	8 +@@ -198,63 +200,63 @@   #define  SSB_SPROM1_BINF_ANTBG_SHIFT	12   #define  SSB_SPROM1_BINF_ANTA		0xC000	/* Available A-PHY antennas */   #define  SSB_SPROM1_BINF_ANTA_SHIFT	14 @@ -811,7 +1306,7 @@   #define  SSB_SPROM3_CCKPO_1M		0x000F	/* 1M Rate PO */   #define  SSB_SPROM3_CCKPO_2M		0x00F0	/* 2M Rate PO */   #define  SSB_SPROM3_CCKPO_2M_SHIFT	4 -@@ -265,100 +265,100 @@ +@@ -265,100 +267,144 @@   #define  SSB_SPROM3_OFDMGPO		0x107A	/* G-PHY OFDM Power Offset (4 bytes, BigEndian) */   /* SPROM Revision 4 */ @@ -819,6 +1314,8 @@  -#define SSB_SPROM4_ETHPHY		0x105A	/* Ethernet PHY settings ?? */  +#define SSB_SPROM4_BFLLO		0x0044	/* Boardflags (low 16 bits) */  +#define SSB_SPROM4_BFLHI		0x0046  /* Board Flags Hi */ ++#define SSB_SPROM4_BFL2LO		0x0048	/* Board flags 2 (low 16 bits) */ ++#define SSB_SPROM4_BFL2HI		0x004A	/* Board flags 2 Hi */  +#define SSB_SPROM4_IL0MAC		0x004C	/* 6 byte MAC address for a/b/g/n */  +#define SSB_SPROM4_CCODE		0x0052	/* Country Code (2 bytes) */  +#define SSB_SPROM4_GPIOA		0x0056	/* Gen. Purpose IO # 0 and 1 */ @@ -861,6 +1358,46 @@   #define  SSB_SPROM4_AGAIN3_SHIFT	8  -#define SSB_SPROM4_BFLHI		0x1046  /* Board Flags Hi */  -#define SSB_SPROM4_MAXP_BG		0x1080  /* Max Power BG in path 1 */ ++#define SSB_SPROM4_TXPID2G01		0x0062 	/* TX Power Index 2GHz */ ++#define  SSB_SPROM4_TXPID2G0		0x00FF ++#define  SSB_SPROM4_TXPID2G0_SHIFT	0 ++#define  SSB_SPROM4_TXPID2G1		0xFF00 ++#define  SSB_SPROM4_TXPID2G1_SHIFT	8 ++#define SSB_SPROM4_TXPID2G23		0x0064 	/* TX Power Index 2GHz */ ++#define  SSB_SPROM4_TXPID2G2		0x00FF ++#define  SSB_SPROM4_TXPID2G2_SHIFT	0 ++#define  SSB_SPROM4_TXPID2G3		0xFF00 ++#define  SSB_SPROM4_TXPID2G3_SHIFT	8 ++#define SSB_SPROM4_TXPID5G01		0x0066 	/* TX Power Index 5GHz middle subband */ ++#define  SSB_SPROM4_TXPID5G0		0x00FF ++#define  SSB_SPROM4_TXPID5G0_SHIFT	0 ++#define  SSB_SPROM4_TXPID5G1		0xFF00 ++#define  SSB_SPROM4_TXPID5G1_SHIFT	8 ++#define SSB_SPROM4_TXPID5G23		0x0068 	/* TX Power Index 5GHz middle subband */ ++#define  SSB_SPROM4_TXPID5G2		0x00FF ++#define  SSB_SPROM4_TXPID5G2_SHIFT	0 ++#define  SSB_SPROM4_TXPID5G3		0xFF00 ++#define  SSB_SPROM4_TXPID5G3_SHIFT	8 ++#define SSB_SPROM4_TXPID5GL01		0x006A 	/* TX Power Index 5GHz low subband */ ++#define  SSB_SPROM4_TXPID5GL0		0x00FF ++#define  SSB_SPROM4_TXPID5GL0_SHIFT	0 ++#define  SSB_SPROM4_TXPID5GL1		0xFF00 ++#define  SSB_SPROM4_TXPID5GL1_SHIFT	8 ++#define SSB_SPROM4_TXPID5GL23		0x006C 	/* TX Power Index 5GHz low subband */ ++#define  SSB_SPROM4_TXPID5GL2		0x00FF ++#define  SSB_SPROM4_TXPID5GL2_SHIFT	0 ++#define  SSB_SPROM4_TXPID5GL3		0xFF00 ++#define  SSB_SPROM4_TXPID5GL3_SHIFT	8 ++#define SSB_SPROM4_TXPID5GH01		0x006E 	/* TX Power Index 5GHz high subband */ ++#define  SSB_SPROM4_TXPID5GH0		0x00FF ++#define  SSB_SPROM4_TXPID5GH0_SHIFT	0 ++#define  SSB_SPROM4_TXPID5GH1		0xFF00 ++#define  SSB_SPROM4_TXPID5GH1_SHIFT	8 ++#define SSB_SPROM4_TXPID5GH23		0x0070 	/* TX Power Index 5GHz high subband */ ++#define  SSB_SPROM4_TXPID5GH2		0x00FF ++#define  SSB_SPROM4_TXPID5GH2_SHIFT	0 ++#define  SSB_SPROM4_TXPID5GH3		0xFF00 ++#define  SSB_SPROM4_TXPID5GH3_SHIFT	8  +#define SSB_SPROM4_MAXP_BG		0x0080  /* Max Power BG in path 1 */   #define  SSB_SPROM4_MAXP_BG_MASK	0x00FF  /* Mask for Max Power BG */   #define  SSB_SPROM4_ITSSI_BG		0xFF00	/* Mask for path 1 itssi_bg */ @@ -900,6 +1437,8 @@  +#define SSB_SPROM5_CCODE		0x0044	/* Country Code (2 bytes) */  +#define SSB_SPROM5_BFLLO		0x004A	/* Boardflags (low 16 bits) */  +#define SSB_SPROM5_BFLHI		0x004C  /* Board Flags Hi */ ++#define SSB_SPROM5_BFL2LO		0x004E	/* Board flags 2 (low 16 bits) */ ++#define SSB_SPROM5_BFL2HI		0x0050	/* Board flags 2 Hi */  +#define SSB_SPROM5_IL0MAC		0x0052	/* 6 byte MAC address for a/b/g/n */  +#define SSB_SPROM5_GPIOA		0x0076	/* Gen. Purpose IO # 0 and 1 */   #define  SSB_SPROM5_GPIOA_P0		0x00FF	/* Pin 0 */ @@ -969,7 +1508,7 @@   #define  SSB_SPROM8_RSSISMF2G		0x000F   #define  SSB_SPROM8_RSSISMC2G		0x00F0   #define  SSB_SPROM8_RSSISMC2G_SHIFT	4 -@@ -366,7 +366,7 @@ +@@ -366,7 +412,7 @@   #define  SSB_SPROM8_RSSISAV2G_SHIFT	8   #define  SSB_SPROM8_BXA2G		0x1800   #define  SSB_SPROM8_BXA2G_SHIFT		11 @@ -978,7 +1517,7 @@   #define  SSB_SPROM8_RSSISMF5G		0x000F   #define  SSB_SPROM8_RSSISMC5G		0x00F0   #define  SSB_SPROM8_RSSISMC5G_SHIFT	4 -@@ -374,47 +374,47 @@ +@@ -374,47 +420,47 @@   #define  SSB_SPROM8_RSSISAV5G_SHIFT	8   #define  SSB_SPROM8_BXA5G		0x1800   #define  SSB_SPROM8_BXA5G_SHIFT		11  | 
