static int extpci_read_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len) { uint32 addr, *reg = NULL, val; int ret = 0; if (pci_disabled || !(addr = config_cmd(sbh, bus, dev, func, off)) || !(reg = (uint32 *) REG_MAP(addr, len)) || BUSPROBE(val, reg)) val = 0xffffffff; val >>= 8 * (off & 3); if (len == 4) *((uint32 *) buf) = val; else if (len == 2) *((uint16 *) buf) = (uint16) val; else if (len == 1) *((uint8 *) buf) = (uint8) val; else ret = -1; if (reg) REG_UNMAP(reg); return ret; }
/* generic kernel variant of si_attach() */ si_t * si_kattach(osl_t *osh) { static bool ksii_attached = FALSE; if (!ksii_attached) { void *regs = REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE); if (si_doattach(&ksii, BCM4710_DEVICE_ID, osh, regs, SI_BUS, NULL, osh != SI_OSH ? &ksii.vars : NULL, osh != SI_OSH ? &ksii.varsz : NULL) == NULL) { if (NULL != ksii.common_info) MFREE(osh, ksii.common_info, sizeof(si_common_info_t)); SI_ERROR(("si_kattach: si_doattach failed\n")); REG_UNMAP(regs); return NULL; } REG_UNMAP(regs); /* save ticks normalized to ms for si_watchdog_ms() */ if (PMUCTL_ENAB(&ksii.pub)) { /* based on 32KHz ILP clock */ wd_msticks = 32; } else { wd_msticks = ALP_CLOCK / 1000; } ksii_attached = TRUE; SI_MSG(("si_kattach done. ccrev = %d, wd_msticks = %d\n", ksii.pub.ccrev, wd_msticks)); } return &ksii.pub; }
static int extpci_write_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len) { uint32 addr, *reg = NULL, val; int ret = 0; if (pci_disabled || !(addr = config_cmd(sbh, bus, dev, func, off)) || !(reg = (uint32 *) REG_MAP(addr, len)) || BUSPROBE(val, reg)) goto done; if (len == 4) val = *((uint32 *) buf); else if (len == 2) { val &= ~(0xffff << (8 * (off & 3))); val |= *((uint16 *) buf) << (8 * (off & 3)); } else if (len == 1) { val &= ~(0xff << (8 * (off & 3))); val |= *((uint8 *) buf) << (8 * (off & 3)); } else ret = -1; W_REG(reg, val); done: if (reg) REG_UNMAP(reg); return ret; }
/* Get access to the RoboSwitch */ void * robo_attach(void *sih) { robo_info_t *robo; si_info_t *sii; nssrabregs_t *regs; /* pointer to chip registers */ struct si_pub *sii_pub = NULL; uint32 base_addr; sii = SI_INFO((si_t*)sih); /* Allocate private state */ if (!(robo = MALLOC(sii->osh, sizeof(robo_info_t)))) { SRAB_ERR(("robo_attach: out of memory")); return NULL; } else { robo_sbh = (void *)robo; } bzero((char *) robo, sizeof(robo_info_t)); robo->sbh = sih; sii_pub = &sii->pub; if (sii_pub->chip == BCM53020_CHIP_ID) { base_addr = NSP_CCB_SRAB_BASE; } else { base_addr = CCB_SRAB_BASE; } if ((regs = (void*)REG_MAP(base_addr, CORE_SIZE)) == NULL) { SRAB_ERR(("robo_attach: can't get base address")); return NULL; } /* printk("%d: robo_attach: regs=0x%x\n",__LINE__,(uint32)regs);*/ robo->regs = regs; #ifdef _KERNEL_ /* Initialize lock */ spin_lock_init(&robo->lock); #endif return robo; }
static void __init sb_extif_serial_init(sb_t * sbh, void *regs, sb_serial_init_fn add) { osl_t *osh = sb_osh(sbh); extifregs_t *eir = (extifregs_t *) regs; sbconfig_t *sb; ulong base; uint irq; int i, n; /* Determine external UART register base */ sb = (sbconfig_t *) ((ulong) eir + SBCONFIGOFF); base = EXTIF_CFGIF_BASE(sb_base(R_REG(osh, &sb->sbadmatch1))); /* Determine IRQ */ irq = sb_irq(sbh); /* Disable GPIO interrupt initially */ W_REG(osh, &eir->gpiointpolarity, 0); W_REG(osh, &eir->gpiointmask, 0); /* Search for external UARTs */ n = 2; for (i = 0; i < 2; i++) { regs = (void *)REG_MAP(base + (i * 8), 8); if (serial_exists(osh, regs)) { /* Set GPIO 1 to be the external UART IRQ */ W_REG(osh, &eir->gpiointmask, 2); /* XXXDetermine external UART clock */ if (add) add(regs, irq, 13500000, 0); } } /* Add internal UART if enabled */ if (R_REG(osh, &eir->corecontrol) & CC_UE) if (add) add((void *)&eir->uartdata, irq, sb_clock(sbh), 2); }
uint32 * spi_reg_map(osl_t *osh, uintptr addr, int size) { return (uint32 *)REG_MAP(addr, size); }
static si_info_t * si_doattach(si_info_t *sii, uint devid, osl_t *osh, void *regs, uint bustype, void *sdh, char **vars, uint *varsz) { struct si_pub *sih = &sii->pub; uint32 w, savewin; chipcregs_t *cc; char *pvars = NULL; uint origidx; ASSERT(GOODREGS(regs)); bzero((uchar*)sii, sizeof(si_info_t)); { if (NULL == (common_info_alloced = (void *)MALLOC(osh, sizeof(si_common_info_t)))) { SI_ERROR(("si_doattach: malloc failed! malloced %dbytes\n", MALLOCED(osh))); return (NULL); } bzero((uchar*)(common_info_alloced), sizeof(si_common_info_t)); } sii->common_info = (si_common_info_t *)common_info_alloced; sii->common_info->attach_count++; savewin = 0; sih->buscoreidx = BADIDX; sii->curmap = regs; sii->sdh = sdh; sii->osh = osh; /* find Chipcommon address */ if (bustype == PCI_BUS) { savewin = OSL_PCI_READ_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32)); if (!GOODCOREADDR(savewin, SI_ENUM_BASE)) savewin = SI_ENUM_BASE; OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, 4, SI_ENUM_BASE); cc = (chipcregs_t *)regs; } else if ((bustype == SDIO_BUS) || (bustype == SPI_BUS)) { cc = (chipcregs_t *)sii->curmap; } else { cc = (chipcregs_t *)REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE); } sih->bustype = bustype; if (bustype != BUSTYPE(bustype)) { SI_ERROR(("si_doattach: bus type %d does not match configured bus type %d\n", bustype, BUSTYPE(bustype))); return NULL; } /* bus/core/clk setup for register access */ if (!si_buscore_prep(sii, bustype, devid, sdh)) { SI_ERROR(("si_doattach: si_core_clk_prep failed %d\n", bustype)); return NULL; } /* ChipID recognition. * We assume we can read chipid at offset 0 from the regs arg. * If we add other chiptypes (or if we need to support old sdio hosts w/o chipcommon), * some way of recognizing them needs to be added here. */ w = R_REG(osh, &cc->chipid); sih->socitype = (w & CID_TYPE_MASK) >> CID_TYPE_SHIFT; /* Might as wll fill in chip id rev & pkg */ sih->chip = w & CID_ID_MASK; sih->chiprev = (w & CID_REV_MASK) >> CID_REV_SHIFT; sih->chippkg = (w & CID_PKG_MASK) >> CID_PKG_SHIFT; if ((CHIPID(sih->chip) == BCM4329_CHIP_ID) && (sih->chippkg != BCM4329_289PIN_PKG_ID)) sih->chippkg = BCM4329_182PIN_PKG_ID; sih->issim = IS_SIM(sih->chippkg); /* scan for cores */ if (CHIPTYPE(sii->pub.socitype) == SOCI_SB) { SI_MSG(("Found chip type SB (0x%08x)\n", w)); sb_scan(&sii->pub, regs, devid); } else if (CHIPTYPE(sii->pub.socitype) == SOCI_AI) { SI_MSG(("Found chip type AI (0x%08x)\n", w)); /* pass chipc address instead of original core base */ ai_scan(&sii->pub, (void *)cc, devid); } else { SI_ERROR(("Found chip of unkown type (0x%08x)\n", w)); return NULL; } /* no cores found, bail out */ if (sii->numcores == 0) { SI_ERROR(("si_doattach: could not find any cores\n")); return NULL; } /* bus/core/clk setup */ origidx = SI_CC_IDX; if (!si_buscore_setup(sii, cc, bustype, savewin, &origidx, regs)) { SI_ERROR(("si_doattach: si_buscore_setup failed\n")); return NULL; } pvars = NULL; if (sii->pub.ccrev >= 20) { cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); W_REG(osh, &cc->gpiopullup, 0); W_REG(osh, &cc->gpiopulldown, 0); si_setcoreidx(sih, origidx); } /* Skip PMU initialization from the Dongle Host. * Firmware will take care of it when it comes up. */ return (sii); }
/* * Initializes UART access. The callback function will be called once * per found UART. */ void BCMINITFN(sb_serial_init)(sb_t *sbh, void (*add)(void *regs, uint irq, uint baud_base, uint reg_shift)) { osl_t *osh; void *regs; ulong base; uint irq; int i, n; osh = sb_osh(sbh); if ((regs = sb_setcore(sbh, SB_EXTIF, 0))) { extifregs_t *eir = (extifregs_t *) regs; sbconfig_t *sb; /* Determine external UART register base */ sb = (sbconfig_t *)((ulong) eir + SBCONFIGOFF); base = EXTIF_CFGIF_BASE(sb_base(R_REG(osh, &sb->sbadmatch1))); /* Determine IRQ */ irq = sb_irq(sbh); /* Disable GPIO interrupt initially */ W_REG(osh, &eir->gpiointpolarity, 0); W_REG(osh, &eir->gpiointmask, 0); /* Search for external UARTs */ n = 2; for (i = 0; i < 2; i++) { regs = (void *) REG_MAP(base + (i * 8), 8); if (serial_exists(osh, regs)) { /* Set GPIO 1 to be the external UART IRQ */ W_REG(osh, &eir->gpiointmask, 2); /* XXXDetermine external UART clock */ if (add) add(regs, irq, 13500000, 0); } } /* Add internal UART if enabled */ if (R_REG(osh, &eir->corecontrol) & CC_UE) if (add) add((void *) &eir->uartdata, irq, sb_clock(sbh), 2); } else if ((regs = sb_setcore(sbh, SB_CC, 0))) { chipcregs_t *cc = (chipcregs_t *) regs; uint32 rev, cap, pll, baud_base, div; /* Default value */ div = 48; /* Determine core revision and capabilities */ rev = sb_corerev(sbh); cap = R_REG(osh, &cc->capabilities); pll = cap & CAP_PLL_MASK; /* Determine IRQ */ irq = sb_irq(sbh); if (pll == PLL_TYPE1) { /* PLL clock */ baud_base = sb_clock_rate(pll, R_REG(osh, &cc->clockcontrol_n), R_REG(osh, &cc->clockcontrol_m2)); div = 1; } else { /* 5354 chip common uart uses a constant clock * frequency of 25MHz */ if (sb_corerev(sbh) == 20) { /* Set the override bit so we don't divide it */ W_REG(osh, &cc->corecontrol, CC_UARTCLKO); baud_base = 25000000; } else if (rev >= 11 && rev != 15) { /* Fixed ALP clock */ baud_base = sb_alp_clock(sbh); div = 1; /* Set the override bit so we don't divide it */ W_REG(osh, &cc->corecontrol, CC_UARTCLKO); } else if (rev >= 3) { /* Internal backplane clock */ baud_base = sb_clock(sbh); div = 2; /* Minimum divisor */ W_REG(osh, &cc->clkdiv, ((R_REG(osh, &cc->clkdiv) & ~CLKD_UART) | div)); } else { /* Fixed internal backplane clock */ baud_base = 88000000; div = 48; } /* Clock source depends on strapping if UartClkOverride is unset */ if ((rev > 0) && ((R_REG(osh, &cc->corecontrol) & CC_UARTCLKO) == 0)) { if ((cap & CAP_UCLKSEL) == CAP_UINTCLK) { /* Internal divided backplane clock */ baud_base /= div; } else { /* Assume external clock of 1.8432 MHz */ baud_base = 1843200; } } } /* Add internal UARTs */ n = cap & CAP_UARTS_MASK; for (i = 0; i < n; i++) { /* Register offset changed after revision 0 */ if (rev) regs = (void *)((ulong) &cc->uart0data + (i * 256)); else regs = (void *)((ulong) &cc->uart0data + (i * 8)); if (add) add(regs, irq, baud_base, 0); } } }
uint32 * sdstd_reg_map(osl_t *osh, int32 addr, int size) { return (uint32 *)REG_MAP(addr, size); }