diff options
| -rw-r--r-- | target/linux/generic/patches-3.0/020-ssb_update.patch | 190 | ||||
| -rw-r--r-- | target/linux/generic/patches-3.0/025-bcma_backport.patch | 494 | 
2 files changed, 684 insertions, 0 deletions
| diff --git a/target/linux/generic/patches-3.0/020-ssb_update.patch b/target/linux/generic/patches-3.0/020-ssb_update.patch new file mode 100644 index 000000000..3282ff0d7 --- /dev/null +++ b/target/linux/generic/patches-3.0/020-ssb_update.patch @@ -0,0 +1,190 @@ +--- a/drivers/ssb/driver_chipcommon_pmu.c ++++ b/drivers/ssb/driver_chipcommon_pmu.c +@@ -417,9 +417,9 @@ static void ssb_pmu_resources_init(struc + 	u32 min_msk = 0, max_msk = 0; + 	unsigned int i; + 	const struct pmu_res_updown_tab_entry *updown_tab = NULL; +-	unsigned int updown_tab_size; ++	unsigned int updown_tab_size = 0; + 	const struct pmu_res_depend_tab_entry *depend_tab = NULL; +-	unsigned int depend_tab_size; ++	unsigned int depend_tab_size = 0; +  + 	switch (bus->chip_id) { + 	case 0x4312: +--- a/drivers/ssb/driver_gige.c ++++ b/drivers/ssb/driver_gige.c +@@ -106,8 +106,9 @@ void gige_pcicfg_write32(struct ssb_gige + 	gige_write32(dev, SSB_GIGE_PCICFG + offset, value); + } +  +-static int ssb_gige_pci_read_config(struct pci_bus *bus, unsigned int devfn, +-				    int reg, int size, u32 *val) ++static int __devinit ssb_gige_pci_read_config(struct pci_bus *bus, ++					      unsigned int devfn, int reg, ++					      int size, u32 *val) + { + 	struct ssb_gige *dev = container_of(bus->ops, struct ssb_gige, pci_ops); + 	unsigned long flags; +@@ -136,8 +137,9 @@ static int ssb_gige_pci_read_config(stru + 	return PCIBIOS_SUCCESSFUL; + } +  +-static int ssb_gige_pci_write_config(struct pci_bus *bus, unsigned int devfn, +-				     int reg, int size, u32 val) ++static int __devinit ssb_gige_pci_write_config(struct pci_bus *bus, ++					       unsigned int devfn, int reg, ++					       int size, u32 val) + { + 	struct ssb_gige *dev = container_of(bus->ops, struct ssb_gige, pci_ops); + 	unsigned long flags; +@@ -166,7 +168,8 @@ static int ssb_gige_pci_write_config(str + 	return PCIBIOS_SUCCESSFUL; + } +  +-static int ssb_gige_probe(struct ssb_device *sdev, const struct ssb_device_id *id) ++static int __devinit ssb_gige_probe(struct ssb_device *sdev, ++				    const struct ssb_device_id *id) + { + 	struct ssb_gige *dev; + 	u32 base, tmslow, tmshigh; +--- a/drivers/ssb/driver_pcicore.c ++++ b/drivers/ssb/driver_pcicore.c +@@ -314,7 +314,7 @@ int ssb_pcicore_pcibios_map_irq(const st + 	return ssb_mips_irq(extpci_core->dev) + 2; + } +  +-static void ssb_pcicore_init_hostmode(struct ssb_pcicore *pc) ++static void __devinit ssb_pcicore_init_hostmode(struct ssb_pcicore *pc) + { + 	u32 val; +  +@@ -379,7 +379,7 @@ static void ssb_pcicore_init_hostmode(st + 	register_pci_controller(&ssb_pcicore_controller); + } +  +-static int pcicore_is_in_hostmode(struct ssb_pcicore *pc) ++static int __devinit pcicore_is_in_hostmode(struct ssb_pcicore *pc) + { + 	struct ssb_bus *bus = pc->dev->bus; + 	u16 chipid_top; +@@ -412,7 +412,7 @@ static int pcicore_is_in_hostmode(struct +  * Workarounds. +  **************************************************/ +  +-static void ssb_pcicore_fix_sprom_core_index(struct ssb_pcicore *pc) ++static void __devinit ssb_pcicore_fix_sprom_core_index(struct ssb_pcicore *pc) + { + 	u16 tmp = pcicore_read16(pc, SSB_PCICORE_SPROM(0)); + 	if (((tmp & 0xF000) >> 12) != pc->dev->core_index) { +@@ -514,13 +514,13 @@ static void ssb_pcicore_pcie_setup_worka +  * Generic and Clientmode operation code. +  **************************************************/ +  +-static void ssb_pcicore_init_clientmode(struct ssb_pcicore *pc) ++static void __devinit ssb_pcicore_init_clientmode(struct ssb_pcicore *pc) + { + 	/* Disable PCI interrupts. */ + 	ssb_write32(pc->dev, SSB_INTVEC, 0); + } +  +-void ssb_pcicore_init(struct ssb_pcicore *pc) ++void __devinit ssb_pcicore_init(struct ssb_pcicore *pc) + { + 	struct ssb_device *dev = pc->dev; +  +--- a/drivers/ssb/main.c ++++ b/drivers/ssb/main.c +@@ -557,7 +557,7 @@ error: + } +  + /* Needs ssb_buses_lock() */ +-static int ssb_attach_queued_buses(void) ++static int __devinit ssb_attach_queued_buses(void) + { + 	struct ssb_bus *bus, *n; + 	int err = 0; +@@ -768,9 +768,9 @@ out: + 	return err; + } +  +-static int ssb_bus_register(struct ssb_bus *bus, +-			    ssb_invariants_func_t get_invariants, +-			    unsigned long baseaddr) ++static int __devinit ssb_bus_register(struct ssb_bus *bus, ++				      ssb_invariants_func_t get_invariants, ++				      unsigned long baseaddr) + { + 	int err; +  +@@ -851,8 +851,8 @@ err_disable_xtal: + } +  + #ifdef CONFIG_SSB_PCIHOST +-int ssb_bus_pcibus_register(struct ssb_bus *bus, +-			    struct pci_dev *host_pci) ++int __devinit ssb_bus_pcibus_register(struct ssb_bus *bus, ++				      struct pci_dev *host_pci) + { + 	int err; +  +@@ -875,9 +875,9 @@ EXPORT_SYMBOL(ssb_bus_pcibus_register); + #endif /* CONFIG_SSB_PCIHOST */ +  + #ifdef CONFIG_SSB_PCMCIAHOST +-int ssb_bus_pcmciabus_register(struct ssb_bus *bus, +-			       struct pcmcia_device *pcmcia_dev, +-			       unsigned long baseaddr) ++int __devinit ssb_bus_pcmciabus_register(struct ssb_bus *bus, ++					 struct pcmcia_device *pcmcia_dev, ++					 unsigned long baseaddr) + { + 	int err; +  +@@ -897,8 +897,9 @@ EXPORT_SYMBOL(ssb_bus_pcmciabus_register + #endif /* CONFIG_SSB_PCMCIAHOST */ +  + #ifdef CONFIG_SSB_SDIOHOST +-int ssb_bus_sdiobus_register(struct ssb_bus *bus, struct sdio_func *func, +-			     unsigned int quirks) ++int __devinit ssb_bus_sdiobus_register(struct ssb_bus *bus, ++				       struct sdio_func *func, ++				       unsigned int quirks) + { + 	int err; +  +@@ -918,9 +919,9 @@ int ssb_bus_sdiobus_register(struct ssb_ + EXPORT_SYMBOL(ssb_bus_sdiobus_register); + #endif /* CONFIG_SSB_PCMCIAHOST */ +  +-int ssb_bus_ssbbus_register(struct ssb_bus *bus, +-			    unsigned long baseaddr, +-			    ssb_invariants_func_t get_invariants) ++int __devinit ssb_bus_ssbbus_register(struct ssb_bus *bus, ++				      unsigned long baseaddr, ++				      ssb_invariants_func_t get_invariants) + { + 	int err; +  +--- a/drivers/ssb/pcihost_wrapper.c ++++ b/drivers/ssb/pcihost_wrapper.c +@@ -53,8 +53,8 @@ static int ssb_pcihost_resume(struct pci + # define ssb_pcihost_resume	NULL + #endif /* CONFIG_PM */ +  +-static int ssb_pcihost_probe(struct pci_dev *dev, +-			     const struct pci_device_id *id) ++static int __devinit ssb_pcihost_probe(struct pci_dev *dev, ++				       const struct pci_device_id *id) + { + 	struct ssb_bus *ssb; + 	int err = -ENOMEM; +@@ -110,7 +110,7 @@ static void ssb_pcihost_remove(struct pc + 	pci_set_drvdata(dev, NULL); + } +  +-int ssb_pcihost_register(struct pci_driver *driver) ++int __devinit ssb_pcihost_register(struct pci_driver *driver) + { + 	driver->probe = ssb_pcihost_probe; + 	driver->remove = ssb_pcihost_remove; diff --git a/target/linux/generic/patches-3.0/025-bcma_backport.patch b/target/linux/generic/patches-3.0/025-bcma_backport.patch new file mode 100644 index 000000000..8f02d9e80 --- /dev/null +++ b/target/linux/generic/patches-3.0/025-bcma_backport.patch @@ -0,0 +1,494 @@ +--- a/drivers/bcma/Kconfig ++++ b/drivers/bcma/Kconfig +@@ -13,6 +13,11 @@ config BCMA + 	  Bus driver for Broadcom specific Advanced Microcontroller Bus + 	  Architecture. +  ++# Support for Block-I/O. SELECT this from the driver that needs it. ++config BCMA_BLOCKIO ++	bool ++	depends on BCMA ++ + config BCMA_HOST_PCI_POSSIBLE + 	bool + 	depends on BCMA && PCI = y +--- a/drivers/bcma/Makefile ++++ b/drivers/bcma/Makefile +@@ -1,4 +1,4 @@ +-bcma-y					+= main.o scan.o core.o ++bcma-y					+= main.o scan.o core.o sprom.o + bcma-y					+= driver_chipcommon.o driver_chipcommon_pmu.o + bcma-y					+= driver_pci.o + bcma-$(CONFIG_BCMA_HOST_PCI)		+= host_pci.o +--- a/drivers/bcma/bcma_private.h ++++ b/drivers/bcma/bcma_private.h +@@ -13,12 +13,15 @@ + struct bcma_bus; +  + /* main.c */ +-extern int bcma_bus_register(struct bcma_bus *bus); +-extern void bcma_bus_unregister(struct bcma_bus *bus); ++int bcma_bus_register(struct bcma_bus *bus); ++void bcma_bus_unregister(struct bcma_bus *bus); +  + /* scan.c */ + int bcma_bus_scan(struct bcma_bus *bus); +  ++/* sprom.c */ ++int bcma_sprom_get(struct bcma_bus *bus); ++ + #ifdef CONFIG_BCMA_HOST_PCI + /* host_pci.c */ + extern int __init bcma_host_pci_init(void); +--- a/drivers/bcma/core.c ++++ b/drivers/bcma/core.c +@@ -19,7 +19,7 @@ bool bcma_core_is_enabled(struct bcma_de + } + EXPORT_SYMBOL_GPL(bcma_core_is_enabled); +  +-static void bcma_core_disable(struct bcma_device *core, u32 flags) ++void bcma_core_disable(struct bcma_device *core, u32 flags) + { + 	if (bcma_aread32(core, BCMA_RESET_CTL) & BCMA_RESET_CTL_RESET) + 		return; +@@ -31,6 +31,7 @@ static void bcma_core_disable(struct bcm + 	bcma_awrite32(core, BCMA_RESET_CTL, BCMA_RESET_CTL_RESET); + 	udelay(1); + } ++EXPORT_SYMBOL_GPL(bcma_core_disable); +  + int bcma_core_enable(struct bcma_device *core, u32 flags) + { +--- a/drivers/bcma/driver_chipcommon_pmu.c ++++ b/drivers/bcma/driver_chipcommon_pmu.c +@@ -53,6 +53,7 @@ static void bcma_pmu_resources_init(stru + 		max_msk = 0xFFFF; + 		break; + 	case 43224: ++	case 43225: + 		break; + 	default: + 		pr_err("PMU resource config unknown for device 0x%04X\n", +@@ -74,6 +75,7 @@ void bcma_pmu_swreg_init(struct bcma_drv + 	case 0x4313: + 	case 0x4331: + 	case 43224: ++	case 43225: + 		break; + 	default: + 		pr_err("PMU switch/regulators init unknown for device " +@@ -96,11 +98,13 @@ void bcma_pmu_workarounds(struct bcma_dr + 		if (bus->chipinfo.rev == 0) { + 			pr_err("Workarounds for 43224 rev 0 not fully " + 				"implemented\n"); +-			bcma_chipco_chipctl_maskset(cc, 0, ~0, 0xF0); ++			bcma_chipco_chipctl_maskset(cc, 0, ~0, 0x00F000F0); + 		} else { + 			bcma_chipco_chipctl_maskset(cc, 0, ~0, 0xF0); + 		} + 		break; ++	case 43225: ++		break; + 	default: + 		pr_err("Workarounds unknown for device 0x%04X\n", + 			bus->chipinfo.id); +--- a/drivers/bcma/driver_pci.c ++++ b/drivers/bcma/driver_pci.c +@@ -161,3 +161,27 @@ void bcma_core_pci_init(struct bcma_drv_ + { + 	bcma_pcicore_serdes_workaround(pc); + } ++ ++int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core, ++			  bool enable) ++{ ++	struct pci_dev *pdev = pc->core->bus->host_pci; ++	u32 coremask, tmp; ++	int err; ++ ++	err = pci_read_config_dword(pdev, BCMA_PCI_IRQMASK, &tmp); ++	if (err) ++		goto out; ++ ++	coremask = BIT(core->core_index) << 8; ++	if (enable) ++		tmp |= coremask; ++	else ++		tmp &= ~coremask; ++ ++	err = pci_write_config_dword(pdev, BCMA_PCI_IRQMASK, tmp); ++ ++out: ++	return err; ++} ++EXPORT_SYMBOL_GPL(bcma_core_pci_irq_ctl); +--- a/drivers/bcma/host_pci.c ++++ b/drivers/bcma/host_pci.c +@@ -65,6 +65,54 @@ static void bcma_host_pci_write32(struct + 	iowrite32(value, core->bus->mmio + offset); + } +  ++#ifdef CONFIG_BCMA_BLOCKIO ++void bcma_host_pci_block_read(struct bcma_device *core, void *buffer, ++			      size_t count, u16 offset, u8 reg_width) ++{ ++	void __iomem *addr = core->bus->mmio + offset; ++	if (core->bus->mapped_core != core) ++		bcma_host_pci_switch_core(core); ++	switch (reg_width) { ++	case sizeof(u8): ++		ioread8_rep(addr, buffer, count); ++		break; ++	case sizeof(u16): ++		WARN_ON(count & 1); ++		ioread16_rep(addr, buffer, count >> 1); ++		break; ++	case sizeof(u32): ++		WARN_ON(count & 3); ++		ioread32_rep(addr, buffer, count >> 2); ++		break; ++	default: ++		WARN_ON(1); ++	} ++} ++ ++void bcma_host_pci_block_write(struct bcma_device *core, const void *buffer, ++			       size_t count, u16 offset, u8 reg_width) ++{ ++	void __iomem *addr = core->bus->mmio + offset; ++	if (core->bus->mapped_core != core) ++		bcma_host_pci_switch_core(core); ++	switch (reg_width) { ++	case sizeof(u8): ++		iowrite8_rep(addr, buffer, count); ++		break; ++	case sizeof(u16): ++		WARN_ON(count & 1); ++		iowrite16_rep(addr, buffer, count >> 1); ++		break; ++	case sizeof(u32): ++		WARN_ON(count & 3); ++		iowrite32_rep(addr, buffer, count >> 2); ++		break; ++	default: ++		WARN_ON(1); ++	} ++} ++#endif ++ + static u32 bcma_host_pci_aread32(struct bcma_device *core, u16 offset) + { + 	if (core->bus->mapped_core != core) +@@ -87,6 +135,10 @@ const struct bcma_host_ops bcma_host_pci + 	.write8		= bcma_host_pci_write8, + 	.write16	= bcma_host_pci_write16, + 	.write32	= bcma_host_pci_write32, ++#ifdef CONFIG_BCMA_BLOCKIO ++	.block_read	= bcma_host_pci_block_read, ++	.block_write	= bcma_host_pci_block_write, ++#endif + 	.aread32	= bcma_host_pci_aread32, + 	.awrite32	= bcma_host_pci_awrite32, + }; +@@ -175,6 +227,7 @@ static DEFINE_PCI_DEVICE_TABLE(bcma_pci_ + 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) }, + 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) }, + 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) }, ++	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) }, + 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) }, + 	{ 0, }, + }; +--- a/drivers/bcma/main.c ++++ b/drivers/bcma/main.c +@@ -89,6 +89,8 @@ static int bcma_register_cores(struct bc + 		switch (bus->hosttype) { + 		case BCMA_HOSTTYPE_PCI: + 			core->dev.parent = &bus->host_pci->dev; ++			core->dma_dev = &bus->host_pci->dev; ++			core->irq = bus->host_pci->irq; + 			break; + 		case BCMA_HOSTTYPE_NONE: + 		case BCMA_HOSTTYPE_SDIO: +@@ -144,6 +146,13 @@ int bcma_bus_register(struct bcma_bus *b + 		bcma_core_pci_init(&bus->drv_pci); + 	} +  ++	/* Try to get SPROM */ ++	err = bcma_sprom_get(bus); ++	if (err) { ++		pr_err("Failed to get SPROM: %d\n", err); ++		return -ENOENT; ++	} ++ + 	/* Register found cores */ + 	bcma_register_cores(bus); +  +@@ -151,13 +160,11 @@ int bcma_bus_register(struct bcma_bus *b +  + 	return 0; + } +-EXPORT_SYMBOL_GPL(bcma_bus_register); +  + void bcma_bus_unregister(struct bcma_bus *bus) + { + 	bcma_unregister_cores(bus); + } +-EXPORT_SYMBOL_GPL(bcma_bus_unregister); +  + int __bcma_driver_register(struct bcma_driver *drv, struct module *owner) + { +--- /dev/null ++++ b/drivers/bcma/sprom.c +@@ -0,0 +1,162 @@ ++/* ++ * Broadcom specific AMBA ++ * SPROM reading ++ * ++ * Licensed under the GNU/GPL. See COPYING for details. ++ */ ++ ++#include "bcma_private.h" ++ ++#include <linux/bcma/bcma.h> ++#include <linux/bcma/bcma_regs.h> ++#include <linux/pci.h> ++#include <linux/io.h> ++#include <linux/dma-mapping.h> ++#include <linux/slab.h> ++ ++#define SPOFF(offset)	((offset) / sizeof(u16)) ++ ++/************************************************** ++ * R/W ops. ++ **************************************************/ ++ ++static void bcma_sprom_read(struct bcma_bus *bus, u16 *sprom) ++{ ++	int i; ++	for (i = 0; i < SSB_SPROMSIZE_WORDS_R4; i++) ++		sprom[i] = bcma_read16(bus->drv_cc.core, ++				       BCMA_CC_SPROM + (i * 2)); ++} ++ ++/************************************************** ++ * Validation. ++ **************************************************/ ++ ++static inline u8 bcma_crc8(u8 crc, u8 data) ++{ ++	/* Polynomial:   x^8 + x^7 + x^6 + x^4 + x^2 + 1   */ ++	static const u8 t[] = { ++		0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B, ++		0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21, ++		0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF, ++		0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5, ++		0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14, ++		0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E, ++		0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80, ++		0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA, ++		0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95, ++		0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF, ++		0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01, ++		0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B, ++		0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA, ++		0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0, ++		0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E, ++		0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34, ++		0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0, ++		0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A, ++		0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54, ++		0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E, ++		0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF, ++		0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5, ++		0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B, ++		0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61, ++		0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E, ++		0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74, ++		0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA, ++		0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0, ++		0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41, ++		0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B, ++		0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5, ++		0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F, ++	}; ++	return t[crc ^ data]; ++} ++ ++static u8 bcma_sprom_crc(const u16 *sprom) ++{ ++	int word; ++	u8 crc = 0xFF; ++ ++	for (word = 0; word < SSB_SPROMSIZE_WORDS_R4 - 1; word++) { ++		crc = bcma_crc8(crc, sprom[word] & 0x00FF); ++		crc = bcma_crc8(crc, (sprom[word] & 0xFF00) >> 8); ++	} ++	crc = bcma_crc8(crc, sprom[SSB_SPROMSIZE_WORDS_R4 - 1] & 0x00FF); ++	crc ^= 0xFF; ++ ++	return crc; ++} ++ ++static int bcma_sprom_check_crc(const u16 *sprom) ++{ ++	u8 crc; ++	u8 expected_crc; ++	u16 tmp; ++ ++	crc = bcma_sprom_crc(sprom); ++	tmp = sprom[SSB_SPROMSIZE_WORDS_R4 - 1] & SSB_SPROM_REVISION_CRC; ++	expected_crc = tmp >> SSB_SPROM_REVISION_CRC_SHIFT; ++	if (crc != expected_crc) ++		return -EPROTO; ++ ++	return 0; ++} ++ ++static int bcma_sprom_valid(const u16 *sprom) ++{ ++	u16 revision; ++	int err; ++ ++	err = bcma_sprom_check_crc(sprom); ++	if (err) ++		return err; ++ ++	revision = sprom[SSB_SPROMSIZE_WORDS_R4 - 1] & SSB_SPROM_REVISION_REV; ++	if (revision != 8) { ++		pr_err("Unsupported SPROM revision: %d\n", revision); ++		return -ENOENT; ++	} ++ ++	return 0; ++} ++ ++/************************************************** ++ * SPROM extraction. ++ **************************************************/ ++ ++static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom) ++{ ++	u16 v; ++	int i; ++ ++	for (i = 0; i < 3; i++) { ++		v = sprom[SPOFF(SSB_SPROM8_IL0MAC) + i]; ++		*(((__be16 *)bus->sprom.il0mac) + i) = cpu_to_be16(v); ++	} ++} ++ ++int bcma_sprom_get(struct bcma_bus *bus) ++{ ++	u16 *sprom; ++	int err = 0; ++ ++	if (!bus->drv_cc.core) ++		return -EOPNOTSUPP; ++ ++	sprom = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16), ++			GFP_KERNEL); ++	if (!sprom) ++		return -ENOMEM; ++ ++	bcma_sprom_read(bus, sprom); ++ ++	err = bcma_sprom_valid(sprom); ++	if (err) ++		goto out; ++ ++	bcma_sprom_extract_r8(bus, sprom); ++ ++out: ++	kfree(sprom); ++	return err; ++} +--- a/include/linux/bcma/bcma.h ++++ b/include/linux/bcma/bcma.h +@@ -6,6 +6,7 @@ +  + #include <linux/bcma/bcma_driver_chipcommon.h> + #include <linux/bcma/bcma_driver_pci.h> ++#include <linux/ssb/ssb.h> /* SPROM sharing */ +  + #include "bcma_regs.h" +  +@@ -31,6 +32,12 @@ struct bcma_host_ops { + 	void (*write8)(struct bcma_device *core, u16 offset, u8 value); + 	void (*write16)(struct bcma_device *core, u16 offset, u16 value); + 	void (*write32)(struct bcma_device *core, u16 offset, u32 value); ++#ifdef CONFIG_BCMA_BLOCKIO ++	void (*block_read)(struct bcma_device *core, void *buffer, ++			   size_t count, u16 offset, u8 reg_width); ++	void (*block_write)(struct bcma_device *core, const void *buffer, ++			    size_t count, u16 offset, u8 reg_width); ++#endif + 	/* Agent ops */ + 	u32 (*aread32)(struct bcma_device *core, u16 offset); + 	void (*awrite32)(struct bcma_device *core, u16 offset, u32 value); +@@ -117,6 +124,8 @@ struct bcma_device { + 	struct bcma_device_id id; +  + 	struct device dev; ++	struct device *dma_dev; ++	unsigned int irq; + 	bool dev_registered; +  + 	u8 core_index; +@@ -179,6 +188,10 @@ struct bcma_bus { +  + 	struct bcma_drv_cc drv_cc; + 	struct bcma_drv_pci drv_pci; ++ ++	/* We decided to share SPROM struct with SSB as long as we do not need ++	 * any hacks for BCMA. This simplifies drivers code. */ ++	struct ssb_sprom sprom; + }; +  + extern inline u32 bcma_read8(struct bcma_device *core, u16 offset) +@@ -208,6 +221,18 @@ void bcma_write32(struct bcma_device *co + { + 	core->bus->ops->write32(core, offset, value); + } ++#ifdef CONFIG_BCMA_BLOCKIO ++extern inline void bcma_block_read(struct bcma_device *core, void *buffer, ++				   size_t count, u16 offset, u8 reg_width) ++{ ++	core->bus->ops->block_read(core, buffer, count, offset, reg_width); ++} ++extern inline void bcma_block_write(struct bcma_device *core, const void *buffer, ++				    size_t count, u16 offset, u8 reg_width) ++{ ++	core->bus->ops->block_write(core, buffer, count, offset, reg_width); ++} ++#endif + extern inline u32 bcma_aread32(struct bcma_device *core, u16 offset) + { + 	return core->bus->ops->aread32(core, offset); +@@ -219,6 +244,7 @@ void bcma_awrite32(struct bcma_device *c + } +  + extern bool bcma_core_is_enabled(struct bcma_device *core); ++extern void bcma_core_disable(struct bcma_device *core, u32 flags); + extern int bcma_core_enable(struct bcma_device *core, u32 flags); +  + #endif /* LINUX_BCMA_H_ */ +--- a/include/linux/bcma/bcma_driver_chipcommon.h ++++ b/include/linux/bcma/bcma_driver_chipcommon.h +@@ -244,6 +244,7 @@ + #define BCMA_CC_REGCTL_DATA		0x065C + #define BCMA_CC_PLLCTL_ADDR		0x0660 + #define BCMA_CC_PLLCTL_DATA		0x0664 ++#define BCMA_CC_SPROM			0x0830 /* SPROM beginning */ +  + /* Data for the PMU, if available. +  * Check availability with ((struct bcma_chipcommon)->capabilities & BCMA_CC_CAP_PMU) +--- a/include/linux/bcma/bcma_driver_pci.h ++++ b/include/linux/bcma/bcma_driver_pci.h +@@ -85,5 +85,7 @@ struct bcma_drv_pci { + #define pcicore_write32(pc, offset, val)	bcma_write32((pc)->core, offset, val) +  + extern void bcma_core_pci_init(struct bcma_drv_pci *pc); ++extern int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, ++				 struct bcma_device *core, bool enable); +  + #endif /* LINUX_BCMA_DRIVER_PCI_H_ */ | 
