Exemple #1
0
/**
 * Use device-specific ChipStatus flags to determine the preferred NVRAM
 * data source.
 */
static bhnd_nvram_src_t
chipc_nvram_src_chipst(struct chipc_softc *sc)
{
	uint8_t		nvram_sel;

	CHIPC_ASSERT_QUIRK(sc, SPROM_CHECK_CHIPST);

	if (CHIPC_QUIRK(sc, SPROM_CHECK_CST_R22)) {
		// TODO: On these devices, the official driver code always
		// assumes SPROM availability if CHIPC_CST_OTP_SEL is not
		// set; we must review against the actual behavior of our
		// BCM4312 hardware
		nvram_sel = CHIPC_GET_ATTR(sc->cst, CST_SPROM_OTP_SEL_R22);
	} else if (CHIPC_QUIRK(sc, SPROM_CHECK_CST_R23)) {
		nvram_sel = CHIPC_GET_ATTR(sc->cst, CST_SPROM_OTP_SEL_R23);
	} else {
		panic("invalid CST OTP/SPROM chipc quirk flags");
	}
	device_printf(sc->dev, "querying chipst for 0x%x, 0x%x\n", sc->ccid.chip_id, sc->cst);

	switch (nvram_sel) {
	case CHIPC_CST_DEFCIS_SEL:
		return (BHND_NVRAM_SRC_CIS);

	case CHIPC_CST_SPROM_SEL:
	case CHIPC_CST_OTP_PWRDN:
		return (BHND_NVRAM_SRC_SPROM);

	case CHIPC_CST_OTP_SEL:
		return (BHND_NVRAM_SRC_OTP);

	default:
		device_printf(sc->dev, "unrecognized OTP/SPROM type 0x%hhx",
		    nvram_sel);
		return (BHND_NVRAM_SRC_NONE);
	}
}
Exemple #2
0
/* Read and parse chipc capabilities */
static int
chipc_read_caps(struct chipc_softc *sc, struct chipc_caps *caps)
{
	uint32_t	cap_reg;
	uint32_t	cap_ext_reg;
	uint32_t	regval;

	/* Fetch cap registers */
	cap_reg = bhnd_bus_read_4(sc->core, CHIPC_CAPABILITIES);
	cap_ext_reg = 0;
	if (CHIPC_QUIRK(sc, SUPPORTS_CAP_EXT))
		cap_ext_reg = bhnd_bus_read_4(sc->core, CHIPC_CAPABILITIES_EXT);

	/* Extract values */
	caps->num_uarts		= CHIPC_GET_BITS(cap_reg, CHIPC_CAP_NUM_UART);
	caps->mipseb		= CHIPC_GET_FLAG(cap_reg, CHIPC_CAP_MIPSEB);
	caps->uart_gpio		= CHIPC_GET_FLAG(cap_reg, CHIPC_CAP_UARTGPIO);
	caps->uart_clock	= CHIPC_GET_BITS(cap_reg, CHIPC_CAP_UCLKSEL);

	caps->extbus_type	= CHIPC_GET_BITS(cap_reg, CHIPC_CAP_EXTBUS);
	caps->pwr_ctrl		= CHIPC_GET_FLAG(cap_reg, CHIPC_CAP_PWR_CTL);
	caps->jtag_master	= CHIPC_GET_FLAG(cap_reg, CHIPC_CAP_JTAGP);

	caps->pll_type		= CHIPC_GET_BITS(cap_reg, CHIPC_CAP_PLL);
	caps->backplane_64	= CHIPC_GET_FLAG(cap_reg, CHIPC_CAP_BKPLN64);
	caps->boot_rom		= CHIPC_GET_FLAG(cap_reg, CHIPC_CAP_ROM);
	caps->pmu		= CHIPC_GET_FLAG(cap_reg, CHIPC_CAP_PMU);
	caps->eci		= CHIPC_GET_FLAG(cap_reg, CHIPC_CAP_ECI);
	caps->sprom		= CHIPC_GET_FLAG(cap_reg, CHIPC_CAP_SPROM);
	caps->otp_size		= CHIPC_GET_BITS(cap_reg, CHIPC_CAP_OTP_SIZE);

	caps->seci		= CHIPC_GET_FLAG(cap_ext_reg, CHIPC_CAP2_SECI);
	caps->gsio		= CHIPC_GET_FLAG(cap_ext_reg, CHIPC_CAP2_GSIO);
	caps->aob		= CHIPC_GET_FLAG(cap_ext_reg, CHIPC_CAP2_AOB);

	/* Fetch OTP size for later IPX controller revisions */
	if (CHIPC_QUIRK(sc, IPX_OTPL_SIZE)) {
		regval = bhnd_bus_read_4(sc->core, CHIPC_OTPLAYOUT);
		caps->otp_size = CHIPC_GET_BITS(regval, CHIPC_OTPL_SIZE);
	}

	/* Determine flash type and parameters */
	caps->cfi_width = 0;
	switch (CHIPC_GET_BITS(cap_reg, CHIPC_CAP_FLASH)) {
	case CHIPC_CAP_SFLASH_ST:
		caps->flash_type = CHIPC_SFLASH_ST;
		break;
	case CHIPC_CAP_SFLASH_AT:
		caps->flash_type = CHIPC_SFLASH_AT;
		break;
	case CHIPC_CAP_NFLASH:
		/* unimplemented */
		caps->flash_type = CHIPC_NFLASH;
		break;
	case CHIPC_CAP_PFLASH:
		caps->flash_type = CHIPC_PFLASH_CFI;

		/* determine cfi width */
		regval = bhnd_bus_read_4(sc->core, CHIPC_FLASH_CFG);
		if (CHIPC_GET_FLAG(regval, CHIPC_FLASH_CFG_DS))
			caps->cfi_width = 2;
		else
			caps->cfi_width = 1;

		break;
	case CHIPC_CAP_FLASH_NONE:
		caps->flash_type = CHIPC_FLASH_NONE;
		break;
			
	}

	/* Handle 4706_NFLASH fallback */
	if (CHIPC_QUIRK(sc, 4706_NFLASH) &&
	    CHIPC_GET_FLAG(cap_reg, CHIPC_CAP_4706_NFLASH))
	{
		caps->flash_type = CHIPC_NFLASH_4706;
	}


	/* Determine NVRAM source. Must occur after the SPROM/OTP/flash
	 * capability flags have been populated. */
	caps->nvram_src = chipc_find_nvram_src(sc, caps);

	/* Determine the SPROM offset within OTP (if any). SPROM-formatted
	 * data is placed within the OTP general use region. */
	caps->sprom_offset = 0;
	if (caps->nvram_src == BHND_NVRAM_SRC_OTP) {
		CHIPC_ASSERT_QUIRK(sc, OTP_IPX);

		/* Bit offset to GUP HW subregion containing SPROM data */
		regval = bhnd_bus_read_4(sc->core, CHIPC_OTPLAYOUT);
		caps->sprom_offset = CHIPC_GET_BITS(regval, CHIPC_OTPL_GUP);

		/* Convert to bytes */
		caps->sprom_offset /= 8;
	}

	return (0);
}