示例#1
0
int bcma_sprom_get(struct bcma_bus *bus)
{
	u16 offset;
	u16 *sprom;
	int err = 0;

	if (!bus->drv_cc.core)
		return -EOPNOTSUPP;

	if (!(bus->drv_cc.capabilities & BCMA_CC_CAP_SPROM))
		return -ENOENT;

	sprom = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
			GFP_KERNEL);
	if (!sprom)
		return -ENOMEM;

	if (bus->chipinfo.id == 0x4331)
		bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, false);

	/* Most cards have SPROM moved by additional offset 0x30 (48 dwords).
	 * According to brcm80211 this applies to cards with PCIe rev >= 6
	 * TODO: understand this condition and use it */
	offset = (bus->chipinfo.id == 0x4331) ? BCMA_CC_SPROM :
		BCMA_CC_SPROM_PCIE6;
	bcma_sprom_read(bus, offset, sprom);

	if (bus->chipinfo.id == 0x4331)
		bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, true);

	err = bcma_sprom_valid(sprom);
	if (err)
		goto out;

	bcma_sprom_extract_r8(bus, sprom);

out:
	kfree(sprom);
	return err;
}
示例#2
0
文件: sprom.c 项目: 03199618/linux
int bcma_sprom_get(struct bcma_bus *bus)
{
	u16 offset = BCMA_CC_SPROM;
	u16 *sprom;
	size_t sprom_sizes[] = { SSB_SPROMSIZE_WORDS_R4,
				 SSB_SPROMSIZE_WORDS_R10, };
	int i, err = 0;

	if (!bus->drv_cc.core)
		return -EOPNOTSUPP;

	if (!bcma_sprom_ext_available(bus)) {
		bool sprom_onchip;

		/*
		 * External SPROM takes precedence so check
		 * on-chip OTP only when no external SPROM
		 * is present.
		 */
		sprom_onchip = bcma_sprom_onchip_available(bus);
		if (sprom_onchip) {
			/* determine offset */
			offset = bcma_sprom_onchip_offset(bus);
		}
		if (!offset || !sprom_onchip) {
			/*
			 * Maybe there is no SPROM on the device?
			 * Now we ask the arch code if there is some sprom
			 * available for this device in some other storage.
			 */
			err = bcma_fill_sprom_with_fallback(bus, &bus->sprom);
			return err;
		}
	}

	if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4331 ||
	    bus->chipinfo.id == BCMA_CHIP_ID_BCM43431)
		bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, false);

	bcma_debug(bus, "SPROM offset 0x%x\n", offset);
	for (i = 0; i < ARRAY_SIZE(sprom_sizes); i++) {
		size_t words = sprom_sizes[i];

		sprom = kcalloc(words, sizeof(u16), GFP_KERNEL);
		if (!sprom)
			return -ENOMEM;

		bcma_sprom_read(bus, offset, sprom, words);
		err = bcma_sprom_valid(bus, sprom, words);
		if (!err)
			break;

		kfree(sprom);
	}

	if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4331 ||
	    bus->chipinfo.id == BCMA_CHIP_ID_BCM43431)
		bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, true);

	if (err) {
		bcma_warn(bus, "Invalid SPROM read from the PCIe card, trying to use fallback SPROM\n");
		err = bcma_fill_sprom_with_fallback(bus, &bus->sprom);
	} else {
		bcma_sprom_extract_r8(bus, sprom);
		kfree(sprom);
	}

	return err;
}