Пример #1
0
/* return the ILP (slowclock) min or max frequency */
static uint32_t
bhnd_pwrctl_slowclk_freq(struct bhnd_pwrctl_softc *sc, bool max_freq)
{
	bhnd_clksrc	slowclk;
	uint32_t	div;
	uint32_t	hz;

	slowclk = bhnd_pwrctl_slowclk_src(sc);

	/* Determine clock divisor */
	if (PWRCTL_QUIRK(sc, PCICLK_CTL)) {
		if (slowclk == BHND_CLKSRC_PCI)
			div = 64;
		else
			div = 32;
	} else if (PWRCTL_QUIRK(sc, SLOWCLK_CTL)) {
		div = bhnd_bus_read_4(sc->res, CHIPC_PLL_SLOWCLK_CTL);
		div = CHIPC_GET_BITS(div, CHIPC_SCC_CD);
		div *= 4;
	} else if (PWRCTL_QUIRK(sc, INSTACLK_CTL)) {
		if (max_freq) {
			div = 1;
		} else {
			div = bhnd_bus_read_4(sc->res, CHIPC_SYS_CLK_CTL);
			div = CHIPC_GET_BITS(div, CHIPC_SYCC_CD);
			div = 4 * (div + 1);
		}
	} else {
		device_printf(sc->dev, "unknown device type\n");
		return (0);
	}

	/* Determine clock frequency */
	switch (slowclk) {
	case BHND_CLKSRC_LPO:
		hz = max_freq ? CHIPC_LPOMAXFREQ : CHIPC_LPOMINFREQ;
		break;
	case BHND_CLKSRC_XTAL:
		hz = max_freq ? CHIPC_XTALMAXFREQ : CHIPC_XTALMINFREQ;
		break;
	case BHND_CLKSRC_PCI:
		hz = max_freq ? CHIPC_PCIMAXFREQ : CHIPC_PCIMINFREQ;
		break;
	default:
		device_printf(sc->dev, "unknown slowclk source %#x\n", slowclk);
		return (0);
	}

	return (hz / div);
}
Пример #2
0
static int
siba_erom_probe_common(struct siba_erom_io *io, const struct bhnd_chipid *hint,
    struct bhnd_chipid *cid)
{
	uint32_t		idreg;
	int			error;

	/* Try using the provided hint. */
	if (hint != NULL) {
		struct siba_core_id sid;

		/* Validate bus type */
		if (hint->chip_type != BHND_CHIPTYPE_SIBA)
			return (ENXIO);

		/*
		 * Verify the first core's IDHIGH/IDLOW identification.
		 * 
		 * The core must be a Broadcom core, but must *not* be
		 * a chipcommon core; those shouldn't be hinted.
		 *
		 * The first core on EXTIF-equipped devices varies, but on the
		 * BCM4710, it's a SDRAM core (0x803).
		 */

		sid = siba_eio_read_core_id(io, 0, 0);

		if (sid.core_info.vendor != BHND_MFGID_BCM)
			return (ENXIO);

		if (sid.core_info.device == BHND_COREID_CC)
			return (EINVAL);

		*cid = *hint;
	} else {
		/* Validate bus type */
		idreg = siba_eio_read_4(io, 0, CHIPC_ID);
		if (CHIPC_GET_BITS(idreg, CHIPC_ID_BUS) != BHND_CHIPTYPE_SIBA)
			return (ENXIO);	

		/* Identify the chipset */
		if ((error = siba_eio_read_chipid(io, SIBA_ENUM_ADDR, cid)))
			return (error);

		/* Verify the chip type */
		if (cid->chip_type != BHND_CHIPTYPE_SIBA)
			return (ENXIO);
	}

	/*
	 * gcc hack: ensure bhnd_chipid.ncores cannot exceed SIBA_MAX_CORES
	 * without triggering build failure due to -Wtype-limits
	 *
	 * if (cid.ncores > SIBA_MAX_CORES)
	 *      return (EINVAL)
	 */
	_Static_assert((2^sizeof(cid->ncores)) <= SIBA_MAX_CORES,
	    "ncores could result in over-read of backing resource");

	return (0);
}
Пример #3
0
/**
 * Calculate the clock speed (in Hz) for a given a set of clockcontrol
 * values.
 * 
 * @param pll_type PLL type (CHIPC_PLL_TYPE*)
 * @param n clock control N register value.
 * @param m clock control M register value.
 */
uint32_t
bhnd_pwrctl_clock_rate(uint32_t pll_type, uint32_t n, uint32_t m)
{
	uint32_t clk_base;
	uint32_t n1, n2, clock, m1, m2, m3, mc;

	n1 = CHIPC_GET_BITS(n, CHIPC_CN_N1);
	n2 = CHIPC_GET_BITS(n, CHIPC_CN_N2);

	switch (pll_type) {
	case CHIPC_PLL_TYPE1:
	case CHIPC_PLL_TYPE3:
	case CHIPC_PLL_TYPE4:
	case CHIPC_PLL_TYPE7:
		n1 = bhnd_pwrctl_factor6(n1);
		n2 += CHIPC_F5_BIAS;
		break;

	case CHIPC_PLL_TYPE2:
		n1 += CHIPC_T2_BIAS;
		n2 += CHIPC_T2_BIAS;
		KASSERT(n1 >= 2 && n1 <= 7, ("invalid n1 value"));
		KASSERT(n2 >= 5 && n2 <= 23, ("invalid n2 value"));
		break;
		
	case CHIPC_PLL_TYPE5:
		return (100000000);

	case CHIPC_PLL_TYPE6:
		if (m & CHIPC_T6_MMASK)
			return (CHIPC_T6_M1);
		else
			return (CHIPC_T6_M0);

	default:
		printf("unsupported PLL type %u\n", pll_type);
		return (0);
	}

	/* PLL types 3 and 7 use BASE2 (25Mhz) */
	if (pll_type == CHIPC_PLL_TYPE3 || pll_type == CHIPC_PLL_TYPE7) {
		clk_base = CHIPC_CLOCK_BASE2;
	} else {
		clk_base = CHIPC_CLOCK_BASE1;
	}

	clock = clk_base * n1 * n2;

	if (clock == 0)
		return (0);

	m1 = CHIPC_GET_BITS(m, CHIPC_M1);
	m2 = CHIPC_GET_BITS(m, CHIPC_M2);
	m3 = CHIPC_GET_BITS(m, CHIPC_M3);
	mc = CHIPC_GET_BITS(m, CHIPC_MC);

	switch (pll_type) {
	case CHIPC_PLL_TYPE1:
	case CHIPC_PLL_TYPE3:
	case CHIPC_PLL_TYPE4:
	case CHIPC_PLL_TYPE7:
		m1 = bhnd_pwrctl_factor6(m1);
		if (pll_type == CHIPC_PLL_TYPE1 || pll_type == CHIPC_PLL_TYPE3)
			m2 += CHIPC_F5_BIAS;
		else
			m2 = bhnd_pwrctl_factor6(m2);

		m3 = bhnd_pwrctl_factor6(m3);

		switch (mc) {
		case CHIPC_MC_BYPASS:	
			return (clock);
		case CHIPC_MC_M1:	
			return (clock / m1);
		case CHIPC_MC_M1M2:	
			return (clock / (m1 * m2));
		case CHIPC_MC_M1M2M3:
			return (clock / (m1 * m2 * m3));
		case CHIPC_MC_M1M3:
			return (clock / (m1 * m3));
		default:
			printf("unsupported pwrctl mc %#x\n", mc);
			return (0);
		}
	case CHIPC_PLL_TYPE2:
		m1 += CHIPC_T2_BIAS;
		m2 += CHIPC_T2M2_BIAS;
		m3 += CHIPC_T2_BIAS;
		KASSERT(m1 >= 2 && m1 <= 7, ("invalid m1 value"));
		KASSERT(m2 >= 3 && m2 <= 10, ("invalid m2 value"));
		KASSERT(m3 >= 2 && m3 <= 7, ("invalid m3 value"));

		if ((mc & CHIPC_T2MC_M1BYP) == 0)
			clock /= m1;
		if ((mc & CHIPC_T2MC_M2BYP) == 0)
			clock /= m2;
		if ((mc & CHIPC_T2MC_M3BYP) == 0)
			clock /= m3;

		return (clock);
	default:
		panic("unhandled PLL type %u\n", pll_type);
	}
}
Пример #4
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);
}