/* 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); }
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); }
/** * 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); } }
/* 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); }