📄 sbutils.c
字号:
uint32 w; uint idx; int reg_val; si = SB_INFO(sbh); /* if not pci bus, we're done */ if (BUSTYPE(si->sb.bustype) != PCI_BUS) return; ASSERT(PCI(si) || PCIE(si)); ASSERT(si->sb.buscoreidx != BADIDX); /* get current core index */ idx = si->curidx; /* we interrupt on this backplane flag number */ ASSERT(GOODREGS(si->curmap)); sb = REGS2SB(si->curmap); sbflag = R_SBREG(si, &sb->sbtpsflag) & SBTPS_NUM0_MASK; /* switch over to pci core */ pciregs = (sbpciregs_t*) sb_setcoreidx(sbh, si->sb.buscoreidx); sb = REGS2SB(pciregs); /* * Enable sb->pci interrupts. Assume * PCI rev 2.3 support was added in pci core rev 6 and things changed.. */ if (PCIE(si) || (PCI(si) && ((si->sb.buscorerev) >= 6))) { /* pci config write to set this core bit in PCIIntMask */ w = OSL_PCI_READ_CONFIG(si->osh, PCI_INT_MASK, sizeof(uint32)); w |= (coremask << PCI_SBIM_SHIFT); OSL_PCI_WRITE_CONFIG(si->osh, PCI_INT_MASK, sizeof(uint32), w); } else { /* set sbintvec bit for our flag number */ OR_SBREG(si, &sb->sbintvec, (1 << sbflag)); } if (PCI(si)) { OR_REG(&pciregs->sbtopci2, (SBTOPCI_PREF|SBTOPCI_BURST)); if (si->sb.buscorerev >= 11) OR_REG(&pciregs->sbtopci2, SBTOPCI_RC_READMULTI); if (si->sb.buscorerev < 5) { SET_SBREG(si, &sb->sbimconfiglow, SBIMCL_RTO_MASK | SBIMCL_STO_MASK, (0x3 << SBIMCL_RTO_SHIFT) | 0x2); sb_commit(sbh); } } /* PCIE workarounds */ if (PCIE(si)) { if ((si->sb.buscorerev == 0) || (si->sb.buscorerev == 1)) { reg_val = sb_pcie_readreg((void *)sbh, (void *)PCIE_PCIEREGS, PCIE_TLP_WORKAROUNDSREG); reg_val |= 0x8; sb_pcie_writereg((void *)sbh, (void *)PCIE_PCIEREGS, PCIE_TLP_WORKAROUNDSREG, reg_val); } if (si->sb.buscorerev == 1) { reg_val = sb_pcie_readreg((void *)sbh, (void *)PCIE_PCIEREGS, PCIE_DLLP_LCREG); reg_val |= (0x40); sb_pcie_writereg(sbh, (void *)PCIE_PCIEREGS, PCIE_DLLP_LCREG, reg_val); } if (si->sb.buscorerev == 0) sb_war30841(si); } /* switch back to previous core */ sb_setcoreidx(sbh, idx);}uint32sb_base(uint32 admatch){ uint32 base; uint type; type = admatch & SBAM_TYPE_MASK; ASSERT(type < 3); base = 0; if (type == 0) { base = admatch & SBAM_BASE0_MASK; } else if (type == 1) { ASSERT(!(admatch & SBAM_ADNEG)); /* neg not supported */ base = admatch & SBAM_BASE1_MASK; } else if (type == 2) { ASSERT(!(admatch & SBAM_ADNEG)); /* neg not supported */ base = admatch & SBAM_BASE2_MASK; } return (base);}uint32sb_size(uint32 admatch){ uint32 size; uint type; type = admatch & SBAM_TYPE_MASK; ASSERT(type < 3); size = 0; if (type == 0) { size = 1 << (((admatch & SBAM_ADINT0_MASK) >> SBAM_ADINT0_SHIFT) + 1); } else if (type == 1) { ASSERT(!(admatch & SBAM_ADNEG)); /* neg not supported */ size = 1 << (((admatch & SBAM_ADINT1_MASK) >> SBAM_ADINT1_SHIFT) + 1); } else if (type == 2) { ASSERT(!(admatch & SBAM_ADNEG)); /* neg not supported */ size = 1 << (((admatch & SBAM_ADINT2_MASK) >> SBAM_ADINT2_SHIFT) + 1); } return (size);}/* return the core-type instantiation # of the current core */uintsb_coreunit(sb_t *sbh){ sb_info_t *si; uint idx; uint coreid; uint coreunit; uint i; si = SB_INFO(sbh); coreunit = 0; idx = si->curidx; ASSERT(GOODREGS(si->curmap)); coreid = sb_coreid(sbh); /* count the cores of our type */ for (i = 0; i < idx; i++) if (si->coreid[i] == coreid) coreunit++; return (coreunit);}static INLINE uint32factor6(uint32 x){ switch (x) { case CC_F6_2: return 2; case CC_F6_3: return 3; case CC_F6_4: return 4; case CC_F6_5: return 5; case CC_F6_6: return 6; case CC_F6_7: return 7; default: return 0; }}/* calculate the speed the SB would run at given a set of clockcontrol values */uint32sb_clock_rate(uint32 pll_type, uint32 n, uint32 m){ uint32 n1, n2, clock, m1, m2, m3, mc; n1 = n & CN_N1_MASK; n2 = (n & CN_N2_MASK) >> CN_N2_SHIFT; if (pll_type == PLL_TYPE6) { if (m & CC_T6_MMASK) return CC_T6_M1; else return CC_T6_M0; } else if ((pll_type == PLL_TYPE1) || (pll_type == PLL_TYPE3) || (pll_type == PLL_TYPE4) || (pll_type == PLL_TYPE7)) { n1 = factor6(n1); n2 += CC_F5_BIAS; } else if (pll_type == PLL_TYPE2) { n1 += CC_T2_BIAS; n2 += CC_T2_BIAS; ASSERT((n1 >= 2) && (n1 <= 7)); ASSERT((n2 >= 5) && (n2 <= 23)); } else if (pll_type == PLL_TYPE5) { return (100000000); } else ASSERT(0); /* PLL types 3 and 7 use BASE2 (25Mhz) */ if ((pll_type == PLL_TYPE3) || (pll_type == PLL_TYPE7)) { clock = CC_CLOCK_BASE2 * n1 * n2; } else clock = CC_CLOCK_BASE1 * n1 * n2; if (clock == 0) return 0; m1 = m & CC_M1_MASK; m2 = (m & CC_M2_MASK) >> CC_M2_SHIFT; m3 = (m & CC_M3_MASK) >> CC_M3_SHIFT; mc = (m & CC_MC_MASK) >> CC_MC_SHIFT; if ((pll_type == PLL_TYPE1) || (pll_type == PLL_TYPE3) || (pll_type == PLL_TYPE4) || (pll_type == PLL_TYPE7)) { m1 = factor6(m1); if ((pll_type == PLL_TYPE1) || (pll_type == PLL_TYPE3)) m2 += CC_F5_BIAS; else m2 = factor6(m2); m3 = factor6(m3); switch (mc) { case CC_MC_BYPASS: return (clock); case CC_MC_M1: return (clock / m1); case CC_MC_M1M2: return (clock / (m1 * m2)); case CC_MC_M1M2M3: return (clock / (m1 * m2 * m3)); case CC_MC_M1M3: return (clock / (m1 * m3)); default: return (0); } } else { ASSERT(pll_type == PLL_TYPE2); m1 += CC_T2_BIAS; m2 += CC_T2M2_BIAS; m3 += CC_T2_BIAS; ASSERT((m1 >= 2) && (m1 <= 7)); ASSERT((m2 >= 3) && (m2 <= 10)); ASSERT((m3 >= 2) && (m3 <= 7)); if ((mc & CC_T2MC_M1BYP) == 0) clock /= m1; if ((mc & CC_T2MC_M2BYP) == 0) clock /= m2; if ((mc & CC_T2MC_M3BYP) == 0) clock /= m3; return (clock); }}/* returns the current speed the SB is running at */uint32sb_clock(sb_t *sbh){ sb_info_t *si; chipcregs_t *cc; uint32 n, m; uint idx; uint32 pll_type, rate; uint intr_val = 0; si = SB_INFO(sbh); idx = si->curidx; pll_type = PLL_TYPE1; INTR_OFF(si, intr_val); /* switch to extif or chipc core */ if ((cc = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0))) { pll_type = R_REG(&cc->capabilities) & CAP_PLL_MASK; n = R_REG(&cc->clockcontrol_n); if (pll_type == PLL_TYPE6) m = R_REG(&cc->clockcontrol_m3); else if (pll_type == PLL_TYPE3) m = R_REG(&cc->clockcontrol_m2); else m = R_REG(&cc->clockcontrol_sb); } else { INTR_RESTORE(si, intr_val); return 0; } /* calculate rate */ rate = sb_clock_rate(pll_type, n, m); if (pll_type == PLL_TYPE3) rate = rate / 2; /* switch back to previous core */ sb_setcoreidx(sbh, idx); INTR_RESTORE(si, intr_val); return rate;}/* change logical "focus" to the gpio core for optimized access */void*sb_gpiosetcore(sb_t *sbh){ sb_info_t *si; si = SB_INFO(sbh); return (sb_setcoreidx(sbh, si->gpioidx));}/* mask&set gpiocontrol bits */uint32sb_gpiocontrol(sb_t *sbh, uint32 mask, uint32 val, uint8 priority){ sb_info_t *si; uint regoff; si = SB_INFO(sbh); regoff = 0; /* gpios could be shared on router platforms */ if ((BUSTYPE(si->sb.bustype) == SB_BUS) && (val || mask)) { mask = priority ? (sb_gpioreservation & mask) : ((sb_gpioreservation | mask) & ~(sb_gpioreservation)); val &= mask; } switch (si->gpioid) { case SB_CC: regoff = OFFSETOF(chipcregs_t, gpiocontrol); break; case SB_PCI: regoff = OFFSETOF(sbpciregs_t, gpiocontrol); break; } return (sb_corereg(si, si->gpioidx, regoff, mask, val));}/* mask&set gpio output enable bits */uint32sb_gpioouten(sb_t *sbh, uint32 mask, uint32 val, uint8 priority){ sb_info_t *si; uint regoff; si = SB_INFO(sbh); regoff = 0; /* gpios could be shared on router platforms */ if ((BUSTYPE(si->sb.bustype) == SB_BUS) && (val || mask)) { mask = priority ? (sb_gpioreservation & mask) : ((sb_gpioreservation | mask) & ~(sb_gpioreservation)); val &= mask; } switch (si->gpioid) { case SB_CC: regoff = OFFSETOF(chipcregs_t, gpioouten); break; case SB_PCI: regoff = OFFSETOF(sbpciregs_t, gpioouten); break; } return (sb_corereg(si, si->gpioidx, regoff, mask, val));}/* mask&set gpio output bits */uint32sb_gpioout(sb_t *sbh, uint32 mask, uint32 val, uint8 priority){ sb_info_t *si; uint regoff; si = SB_INFO(sbh); regoff = 0; /* gpios could be shared on router platforms */ if ((BUSTYPE(si->sb.bustype) == SB_BUS) && (val || mask)) { mask = priority ? (sb_gpioreservation & mask) : ((sb_gpioreservation | mask) & ~(sb_gpioreservation)); val &= mask; } switch (si->gpioid) { case SB_CC: regoff = OFFSETOF(chipcregs_t, gpioout); break; case SB_PCI: regoff = OFFSETOF(sbpciregs_t, gpioout); break; } return (sb_corereg(si, si->gpioidx, regoff, mask, val));}/* reserve one gpio */uint32sb_gpioreserve(sb_t *sbh, uint32 gpio_bitmask, uint8 priority){ sb_info_t *si; si = SB_INFO(sbh); /* only cores on SB_BUS share GPIO's and only applcation users need to * reserve/release GPIO */ if ((BUSTYPE(si->sb.bustype) != SB_BUS) || (!priority)) { ASSERT((BUSTYPE(si->sb.bustype) == SB_BUS) && (priority)); return -1; } /* make sure only one bit is set */ if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) { ASSERT((gpio_bitmask) && !((gpio_bitmask) & (gpio_bitmask - 1))); return -1; } /* already reserved */ if (sb_gpioreservation & gpio_bitmask) return -1; /* set reservation */ sb_gpioreservation |= gpio_bitmask; return sb_gpioreservation;}/* release one gpio *//* * releasing the gpio doesn't change the current value on the GPIO last write value * persists till some one overwrites it*/uint32sb_gpiorelease(sb_t *sbh, uint32 gpio_bitmask, uint8 priority){ sb_info_t *si; si = SB_INFO(sbh); /* only cores on SB_BUS share GPIO's and only applcation users need to * reserve/release GPIO */ if ((BUSTYPE(si->sb.bustype) != SB_BUS) || (!priority)) { ASSERT((BUSTYPE(si->sb.bustype) == SB_BUS) && (priority)); return -1; } /* make sure only one bit is set */ if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) { ASSERT((gpio_bitmask) && !((gpio_bitmask) & (gpio_bitmask - 1))); return -1; } /* already released */ if (!(sb_gpioreservation & gpio_bitmask)) return -1; /* clear reservation */ sb_gpioreservation &= ~gpio_bitmask; return sb_gpioreservation;}/* return the current gpioin register value */uint32sb_gpioin(sb_t *sbh){ sb_info_t *si; uint regoff; si = SB_INFO(sbh); regoff = 0; switch (si->gpioid) { case SB_CC: regoff = OFFSETOF(chipcregs_t, gpioin); break; case SB_PCI: regoff = OFFSETOF(sbpciregs_t, gpioin); break; } return (sb_corereg(si, si->gpioidx, regoff, 0, 0));}/* mask&set gpio interrupt polarity bits */uint32sb_gpiointpolarity(sb_t *sbh, uint32 mask, uint32 val, uint8 priority){ sb_info_t *si; uint regoff; si = SB_INFO(sbh); regoff = 0; /* gpios could be shared on router platforms */ if ((BUSTYPE(si->sb.bustype) == SB_BUS) && (val || mask)) { mask = priority ? (sb_gpioreservation & mask) : ((sb_gpioreservation | mask) & ~(sb_gpioreservation)); val &= mask; } switch (si->gpioid) { case SB_CC: regoff = OFFSETOF(chipcregs_t, gpiointpolarity); break; case SB_PCI: /* pci gpio implementation does not support interrupt polarity */ ASSERT(0); break; } return (sb_corereg(si, si->gpioidx, regoff, mask, val));}/* mask&set gpio interrupt mask bits */uint32sb_gpiointmask(sb_t *sbh, uint32 mask, uint32 val, uint8 priority){ sb_info_t *si; uint regoff; si = SB_INFO(sbh); regoff = 0; /* gpios could be shared on router platforms */ if ((BUSTYPE(si->sb.bustype) == SB_BUS) && (val || mask)) { mask = priority ? (sb_gpioreservation & mask) : ((sb_gpioreservation | mask) & ~(sb_gpioreservation)); val &= mask; } switch (si->gpioid) { case SB_CC: regoff = OFFSETOF(chipcregs_t, gpiointmask); break; case SB_PCI: /* pci gpio implementation does not support interrupt mask */ ASSERT(0); break; } return (sb_corereg(si, si->gpioidx, regoff, mask, val));}/* assign the gpio to an led */uint32sb_gpioled(sb_t *sbh, uint32 mask, uint32 val){ sb_info_t *si; si = SB_INFO(sbh); if (si->sb.ccrev < 16) return -1; /* gpio led powersave reg */ return (sb_corereg(si, 0, OFFSETOF(chipcregs_t, gpiotimeroutmask), mask, val));}/* mask&set gpio timer val */uint32sb_gpiotimerval(sb_t *sbh, uint32 mask, uint32 gpiotimerval){ sb_info_t *si; si = SB_INFO(sbh); if (si->sb.ccrev < 16) return -1; return (sb_corereg(si, 0, OFFSETOF(chipcregs_t, gpiotimerval), mask, gpiotimerval));}/* return the slow clock source - LPO, XTAL, or PCI */static uintsb_slowclk_src(sb_info_t *si){ chipcregs_t *cc; ASSERT(sb_coreid(&si->sb) == SB_CC); if (si->sb.ccrev < 6) { if ((BUSTYPE(si->sb.bustype) == PCI_BUS) && (OSL_PCI_READ_CONFIG(si->osh, PCI_GPIO_OUT, sizeof(uint32)) & PCI_CFG_GPIO_SCS)) return (SCC_SS_PCI); else return (SCC_SS_XTAL); } else if (si->sb.ccrev < 10) { cc = (chipcregs_t*) sb_setcoreidx(&si->sb, si->curidx); return (R_REG(&cc->slow_clk_ctl) & SCC_SS_MASK); } else /* Insta-clock */ return (SCC_SS_XTAL);}/* return the ILP (slowclock) min or max frequency */static uintsb_slowclk_freq(sb_info_t *si, bool max){ chipcregs_t *cc; uint32 slowclk; uint div; ASSERT(sb_coreid(&si->sb) == SB_CC); cc = (chipcregs_t*) sb_setcoreidx(&si->sb, si->curidx); /* shouldn't be here unless we've established the chip has dynamic clk control */ ASSERT(R_REG(&cc->capabilities) & CAP_PWR_CTL); slowclk = sb_slowclk_src(si); if (si->sb.ccrev < 6) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -