/* * Interface to register chipc secondary isr */ bool BCMINITFN(sb_cc_register_isr) (sb_t * sbh, cc_isr_fn isr, uint32 ccintmask, void *cbdata) { bool done = FALSE; chipcregs_t *regs; uint origidx; uint i; /* Save the current core index */ origidx = sb_coreidx(sbh); regs = sb_setcore(sbh, SB_CC, 0); ASSERT(regs); for (i = 0; i < MAX_CC_INT_SOURCE; i++) { if (cc_isr_desc[i].isr == NULL) { cc_isr_desc[i].isr = isr; cc_isr_desc[i].cbdata = cbdata; cc_isr_desc[i].intmask = ccintmask; done = TRUE; break; } } if (done) { cc_intmask = R_REG(sb_osh(sbh), ®s->intmask); cc_intmask |= ccintmask; W_REG(sb_osh(sbh), ®s->intmask, cc_intmask); } /* restore original coreidx */ sb_setcoreidx(sbh, origidx); return done; }
static uint32 config_cmd(sb_t *sbh, uint bus, uint dev, uint func, uint off) { uint coreidx; sbpciregs_t *regs; uint32 addr = 0; /* CardBusMode supports only one device */ if (cardbus && dev > 1) return 0; coreidx = sb_coreidx(sbh); regs = (sbpciregs_t *) sb_setcore(sbh, SB_PCI, 0); /* Type 0 transaction */ if (bus == 1) { /* Skip unwired slots */ if (dev < PCI_SLOT_MAX) { /* Slide the PCI window to the appropriate slot */ W_REG(®s->sbtopci1, SBTOPCI_CFG0 | ((1 << (dev + 16)) & SBTOPCI1_MASK)); addr = SB_PCI_CFG | ((1 << (dev + 16)) & ~SBTOPCI1_MASK) | (func << 8) | (off & ~3); } } /* Type 1 transaction */ else { W_REG(®s->sbtopci1, SBTOPCI_CFG1); addr = SB_PCI_CFG | (bus << 16) | (dev << 11) | (func << 8) | (off & ~3); } sb_setcoreidx(sbh, coreidx); return addr; }
void __init bcm947xx_time_init(void) { unsigned int hz; extifregs_t *eir; /* * Use deterministic values for initial counter interrupt * so that calibrate delay avoids encountering a counter wrap. */ write_c0_count(0); write_c0_compare(0xffff); if (!(hz = sb_mips_clock(sbh))) hz = 100000000; #if defined(CONFIG_BCM94702_CPCI) || defined(CONFIG_BCM94704_CPCI) /* Init RTC */ rtc17xx_tod_init(); rtc17xx_tod_print(); /* Use RTC from local bus */ rtc_get_time = rtc17xx_get_time; rtc_set_time = rtc17xx_set_time; #endif printk("CPU: BCM%04x rev %d at %d MHz\n", sb_chip(sbh), sb_chiprev(sbh), (hz + 500000) / 1000000); /* Set MIPS counter frequency for fixed_rate_gettimeoffset() */ mips_hpt_frequency = hz / 2; /* Set watchdog interval in ms */ watchdog = simple_strtoul(nvram_safe_get("watchdog"), NULL, 0); /* Set panic timeout in seconds */ panic_timeout = watchdog / 1000; /* Setup blink */ if ((eir = sb_setcore(sbh, SB_EXTIF, 0))) { sbconfig_t *sb = (sbconfig_t *) ((unsigned int) eir + SBCONFIGOFF); unsigned long base = EXTIF_CFGIF_BASE(sb_base (readl((void *) (&sb->sbadmatch1)))); mcr = (u8 *) ioremap_nocache(base + UART_MCR, 1); } }
static uint32 config_cmd(sb_t *sbh, uint bus, uint dev, uint func, uint off) { uint coreidx; sbpciregs_t *regs; uint32 addr = 0; osl_t *osh; /* CardBusMode supports only one device */ if (cardbus && dev > 1) return 0; osh = sb_osh(sbh); coreidx = sb_coreidx(sbh); regs = (sbpciregs_t *) sb_setcore(sbh, SB_PCI, 0); /* Type 0 transaction */ if (bus == 1) { /* Skip unwired slots */ if (dev < PCI_SLOT_MAX) { uint32 win; /* Slide the PCI window to the appropriate slot */ win = (SBTOPCI_CFG0 | ((1 << (dev + PCI_SLOTAD_MAP)) & SBTOPCI1_MASK)); W_REG(osh, ®s->sbtopci1, win); addr = SB_PCI_CFG | ((1 << (dev + PCI_SLOTAD_MAP)) & ~SBTOPCI1_MASK) | (func << PCICFG_FUN_SHIFT) | (off & ~3); } } else { /* Type 1 transaction */ W_REG(osh, ®s->sbtopci1, SBTOPCI_CFG1); addr = SB_PCI_CFG | (bus << PCICFG_BUS_SHIFT) | (dev << PCICFG_SLOT_SHIFT) | (func << PCICFG_FUN_SHIFT) | (off & ~3); } sb_setcoreidx(sbh, coreidx); return addr; }
/* * Initialize jtag master and return handle for * jtag_rwreg. Returns NULL on failure. */ void *sb_jtagm_init(sb_t * sbh, uint clkd, bool exttap) { void *regs; if ((regs = sb_setcore(sbh, SB_CC, 0)) != NULL) { chipcregs_t *cc = (chipcregs_t *) regs; uint32 tmp; /* * Determine jtagm availability from * core revision and capabilities. */ /* * Corerev 10 has jtagm, but the only chip * with it does not have a mips, and * the layout of the jtagcmd register is * different. We'll only accept >= 11. */ if (sbh->ccrev < 11) return (NULL); if ((sbh->cccaps & CC_CAP_JTAGP) == 0) return (NULL); /* Set clock divider if requested */ if (clkd != 0) { tmp = R_REG(osh, &cc->clkdiv); tmp = (tmp & ~CLKD_JTAG) | ((clkd << CLKD_JTAG_SHIFT) & CLKD_JTAG); W_REG(osh, &cc->clkdiv, tmp); } /* Enable jtagm */ tmp = JCTRL_EN | (exttap ? JCTRL_EXT_EN : 0); W_REG(osh, &cc->jtagctrl, tmp); } return (regs); }
static bool nvram_reset(void *sbh) { chipcregs_t *cc; char *value; uint32 watchdog = 0, gpio; uint idx, msec; idx = sb_coreidx(sbh); /* Check if we were soft reset */ if ((cc = sb_setcore(sbh, SB_CC, 0))) { watchdog = R_REG(&cc->intstatus) & 0x80000000; sb_setcoreidx(sbh, idx); } if (watchdog) return FALSE; value = nvram_get("reset_gpio"); if (!value) return FALSE; gpio = (uint32) bcm_atoi(value); if (gpio > 7) return FALSE; /* Setup GPIO input */ sb_gpioouten(sbh, (1 << gpio), 0); /* GPIO reset is asserted low */ for (msec = 0; msec < 5000; msec++) { if (sb_gpioin(sbh) & (1 << gpio)) return FALSE; OSL_DELAY(1000); } return TRUE; }
int BCMINITFN(nvram_init)(void *sbh) { uint idx; bool isemb; int ret; idx = sb_coreidx(sbh); if (sb_setcore(sbh, SB_CC, 0) != NULL) { flash_base = SB_FLASH2; sb_setcoreidx(sbh, idx); } else flash_base = SB_FLASH1; /* Temporarily initialize with embedded NVRAM */ nvram_header = BCMINIT(find_nvram)(TRUE, &isemb); ret = BCMINIT(_nvram_init)(); if (ret == 0) { /* Restore defaults from embedded NVRAM if button held down */ if (BCMINIT(nvram_reset)(sbh)) { return 1; } BCMINIT(_nvram_exit)(); } /* Find NVRAM */ nvram_header = BCMINIT(find_nvram)(FALSE, &isemb); ret = BCMINIT(_nvram_init)(); if (ret == 0) { /* Restore defaults if embedded NVRAM used */ if (nvram_header && isemb) { ret = 1; } } return ret; }
/* * Read host bridge PCI config registers from Silicon Backplane (>=rev8). * * It returns TRUE to indicate that access to the host bridge's pci config * from SB is ok, and values in 'addr' and 'val' are valid. * * It can only read registers at multiple of 4-bytes. Callers must pick up * needed bytes from 'val' based on 'off' value. Value in 'addr' reflects * the register address where value in 'val' is read. */ static bool sb_pcihb_read_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, uint32 **addr, uint32 *val) { sbpciregs_t *regs; osl_t *osh; uint coreidx; bool ret = FALSE; /* sanity check */ ASSERT(bus == 1); ASSERT(dev == pci_hbslot); ASSERT(func == 0); osh = sb_osh(sbh); /* read pci config when core rev >= 8 */ coreidx = sb_coreidx(sbh); regs = (sbpciregs_t *)sb_setcore(sbh, SB_PCI, 0); if (regs && sb_corerev(sbh) >= PCI_HBSBCFG_REV) { *addr = (uint32 *)®s->pcicfg[func][off >> 2]; *val = R_REG(osh, *addr); ret = TRUE; }
/* * 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); } } }
/* * Initializes UART access. The callback function will be called once * per found UART. */ void BCMINITFN(sb_serial_init) (sb_t * sbh, sb_serial_init_fn add) { osl_t *osh; void *regs; chipcregs_t *cc; uint32 rev, cap, pll, baud_base, div; uint irq; int i, n; osh = sb_osh(sbh); regs = sb_setcore(sbh, SB_EXTIF, 0); if (regs) { sb_extif_serial_init(sbh, regs, add); return; } cc = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0); ASSERT(cc); /* Determine core revision and capabilities */ rev = sbh->ccrev; cap = sbh->cccaps; pll = cap & CC_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; /* Turn off UART clock before switching clock source */ if (rev >= 21) AND_REG(osh, &cc->corecontrol, ~CC_UARTCLKEN); /* Set the override bit so we don't divide it */ OR_REG(osh, &cc->corecontrol, CC_UARTCLKO); if (rev >= 21) OR_REG(osh, &cc->corecontrol, CC_UARTCLKEN); } 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 & CC_CAP_UCLKSEL) == CC_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 & CC_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); } }
/* Probe for NVRAM header */ static void __init early_nvram_init(void) { struct nvram_header *header; chipcregs_t *cc; struct sflash *info = NULL; int i; uint32 base, off, lim; u32 *src, *dst; if ((cc = sb_setcore(sbh, SB_CC, 0)) != NULL) { base = KSEG1ADDR(SB_FLASH2); switch (readl(&cc->capabilities) & CAP_FLASH_MASK) { case PFLASH: lim = SB_FLASH2_SZ; break; case SFLASH_ST: case SFLASH_AT: if ((info = sflash_init(cc)) == NULL) return; lim = info->size; break; case FLASH_NONE: default: return; } } else { /* extif assumed, Stop at 4 MB */ base = KSEG1ADDR(SB_FLASH1); lim = SB_FLASH1_SZ; } /* XXX: hack for supporting the CFE environment stuff on WGT634U */ src = (u32 *) KSEG1ADDR(base + 8 * 1024 * 1024 - 0x2000); dst = (u32 *) nvram_buf; if ((lim == 0x02000000) && ((*src & 0xff00ff) == 0x000001)) { printk("early_nvram_init: WGT634U NVRAM found.\n"); for (i = 0; i < 0x1ff0; i++) { if (*src == 0xFFFFFFFF) break; *dst++ = *src++; } return; } off = FLASH_MIN; while (off <= lim) { /* Windowed flash access */ header = (struct nvram_header *) KSEG1ADDR(base + off - NVRAM_SPACE); if (header->magic == NVRAM_MAGIC) goto found; off <<= 1; } /* Try embedded NVRAM at 4 KB and 1 KB as last resorts */ header = (struct nvram_header *) KSEG1ADDR(base + 4 KB); if (header->magic == NVRAM_MAGIC) goto found; header = (struct nvram_header *) KSEG1ADDR(base + 1 KB); if (header->magic == NVRAM_MAGIC) goto found; printk("early_nvram_init: NVRAM not found\n"); return; found: src = (u32 *) header; dst = (u32 *) nvram_buf; for (i = 0; i < sizeof(struct nvram_header); i += 4) *dst++ = *src++; for (; i < header->len && i < NVRAM_SPACE; i += 4) *dst++ = ltoh32(*src++); }
/* * Setup the gige core. * Resetting the core will lose all settings. */ void sb_gige_init(sb_t *sbh, uint32 unit, bool *rgmii) { volatile pci_config_regs *pci; sbgige_pcishim_t *ocp; sbconfig_t *sb; osl_t *osh; uint32 statelow; uint32 statehigh; uint32 base; uint32 idx; void *regs; /* Sanity checks */ ASSERT(sbh); ASSERT(rgmii); idx = sb_coreidx(sbh); /* point to the gige core registers */ regs = sb_setcore(sbh, SB_GIGETH, unit); ASSERT(regs); osh = sb_osh(sbh); pci = &((sbgige_t *)regs)->pcicfg; ocp = &((sbgige_t *)regs)->pcishim; sb = &((sbgige_t *)regs)->sbconfig; /* Enable the core clock and memory access */ if (!sb_iscoreup(sbh)) sb_core_reset(sbh, 0, 0); /* * Setup the 64K memory-mapped region base address through BAR0. * Leave the other BAR values alone. */ base = sb_base(R_REG(osh, &sb->sbadmatch1)); W_REG(osh, &pci->base[0], base); W_REG(osh, &pci->base[1], 0); /* * Enable the PCI memory access anyway. Any PCI config commands * issued before the core is enabled will go to the emulation * only and will not go to the real PCI config registers. */ OR_REG(osh, &pci->command, 2); /* * Enable the posted write flush scheme as follows: * * - Enable flush on any core register read * - Enable timeout on the flush * - Disable the interrupt mask when flushing * * This differs from the default setting only in that interrupts are * not masked. Since posted writes are not flushed on interrupt, the * driver must explicitly request a flush in its interrupt handling * by reading a core register. */ W_REG(osh, &ocp->FlushStatusControl, 0x68); /* * Determine whether the GbE is in GMII or RGMII mode. This is * indicated in bit 16 of the SBTMStateHigh register, which is * part of the core-specific flags field. * * For GMII, bypass the Rx/Tx DLLs, i.e. add no delay to RXC/GTXC * within the core. For RGMII, do not bypass the DLLs, resulting * in added delay for RXC/GTXC. The SBTMStateLow register contains * the controls for doing this in the core-specific flags field: * * bit 24 - Enable DLL controls * bit 20 - Bypass Rx DLL * bit 19 - Bypass Tx DLL */ statelow = R_REG(osh, &sb->sbtmstatelow); /* DLL controls */ statehigh = R_REG(osh, &sb->sbtmstatehigh); /* GMII/RGMII mode */ if ((statehigh & (1 << 16)) != 0) /* RGMII */ { statelow &= ~(1 << 20); /* no Rx bypass (delay) */ statelow &= ~(1 << 19); /* no Tx bypass (delay) */ *rgmii = TRUE; } else /* GMII */ { statelow |= (1 << 20); /* Rx bypass (no delay) */ statelow |= (1 << 19); /* Tx bypass (no delay) */ *rgmii = FALSE; } statelow |= (1 << 24); /* enable DLL controls */ W_REG(osh, &sb->sbtmstatelow, statelow); sb_setcoreidx(sbh, idx); }
/* Read the flash ID and set the globals */ int sysFlashInit(char *flash_str) { osl_t *osh; uint32 fltype = PFLASH; uint16 flash_vendid = 0; uint16 flash_devid = 0; int idx; struct sflash *sflash; /* * Check for serial flash. */ sbh = sb_kattach(SB_OSH); ASSERT(sbh); osh = sb_osh(sbh); flashutl_base = (uint8*)OSL_UNCACHED(SB_FLASH1); flashutl_wsz = sizeof(uint16); cc = (chipcregs_t *)sb_setcore(sbh, SB_CC, 0); if (cc) { flashutl_base = (uint8*)OSL_UNCACHED(SB_FLASH2); flashutl_wsz = (R_REG(osh, &cc->flash_config) & CC_CFG_DS) ? sizeof(uint16) : sizeof(uint8); /* Select SFLASH ? */ fltype = R_REG(osh, &cc->capabilities) & CC_CAP_FLASH_MASK; if (fltype == SFLASH_ST || fltype == SFLASH_AT) { sflash = sflash_init(sbh, cc); flashutl_cmd = &sflash_cmd_t; flashutl_desc = &sflash_desc; flashutl_desc->size = sflash->size; if (flash_str) sprintf(flash_str, "SFLASH %d kB", sflash->size/1024); return (0); } } ASSERT(flashutl_wsz == sizeof(uint8) || flashutl_wsz == sizeof(uint16)); /* * Parallel flash support * Some flashes have different unlock addresses, try each it turn */ for (idx = 0; fltype == PFLASH && idx < ARRAYSIZE(flash_cmds); idx ++) { flashutl_cmd = &flash_cmds[idx]; if (flashutl_cmd->type == OLD) continue; if (flashutl_cmd->read_id) cmd(flashutl_cmd->read_id, CMD_ADDR); #ifdef MIPSEB flash_vendid = flash_readword(FLASH_ADDR(2)); flash_devid = flash_readword(FLASH_ADDR(0)); #else flash_vendid = flash_readword(FLASH_ADDR(0)); flash_devid = flash_readword(FLASH_ADDR(2)); #endif /* MIPSEB */ /* Funky AMD, uses 3 byte device ID so use first byte (4th addr) to * identify it is a 3-byte ID and use the next two bytes (5th & 6th addr) * to form a word for unique identification of format xxyy, where * xx = 5th addr and yy = 6th addr */ if ((flash_vendid == 1) && (flash_devid == 0x227e)) { /* Get real devid */ uint16 flash_devid_5th; #ifdef MIPSEB flash_devid_5th = flash_readword(FLASH_ADDR(0x1e)) << 8; flash_devid = (flash_readword(FLASH_ADDR(0x1c)) & 0xff) | flash_devid_5th; #else flash_devid_5th = flash_readword(FLASH_ADDR(0x1c)) << 8; flash_devid = (flash_readword(FLASH_ADDR(0x1e)) & 0xff) | flash_devid_5th; #endif /* MIPSEB */ } flashutl_desc = flashes; while (flashutl_desc->mfgid != 0 && !(flashutl_desc->mfgid == flash_vendid && flashutl_desc->devid == flash_devid)) { flashutl_desc++; } if (flashutl_desc->mfgid != 0) break; } if (flashutl_desc->mfgid == 0) { flashutl_desc = NULL; flashutl_cmd = NULL; } else { flashutl_cmd = flash_cmds; while (flashutl_cmd->type != 0 && flashutl_cmd->type != flashutl_desc->type) flashutl_cmd++; if (flashutl_cmd->type == 0) flashutl_cmd = NULL; } if (flashutl_cmd != NULL) { flash_reset(); } if (flashutl_desc == NULL) { if (flash_str) sprintf(flash_str, "UNKNOWN 0x%x 0x%x", flash_vendid, flash_devid); DPRINT(("Flash type UNKNOWN\n")); return 1; } if (flash_str) strcpy(flash_str, flashutl_desc->desc); DPRINT(("Flash type \"%s\"\n", flashutl_desc->desc)); return 0; }
/* Read the flash ID and set the globals */ int sysFlashInit(char *flash_str) { uint32 fltype = PFLASH; uint16 flash_vendid = 0; uint16 flash_devid = 0; uint16* flash = (uint16*)0xbfc00000; int idx; struct sflash *sflash; void *sbh; /* * Check for serial flash. */ sbh = sb_kattach(); ASSERT(sbh); cc = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0); if (cc) { flash = (uint16*)0xbc000000; fltype = R_REG(&cc->capabilities) & CAP_FLASH_MASK; /* Select SFLASH ? */ if (fltype == SFLASH_ST || fltype == SFLASH_AT) { sflash = sflash_init(cc); flashutl_cmd = &sflash_cmd_t; flashutl_desc = &sflash_desc; flashutl_desc->size = sflash->size; if (flash_str) sprintf(flash_str, "SFLASH %d kB", sflash->size/1024); return(0); } } flashutl_base = (uint8*)flash; /* * Parallel flash support * Some flashes have different unlock addresses, try each it turn */ idx = sizeof(flash_cmds)/sizeof(flash_cmds_t) - 2; flashutl_cmd = &flash_cmds[idx--]; while((fltype == PFLASH) && flashutl_cmd->type) { if (flashutl_cmd->read_id) cmd(flashutl_cmd->read_id, CMD_ADDR); #ifdef MIPSEB flash_vendid = *(flash + 1); flash_devid = *flash; #else flash_vendid = *flash; flash_devid = *(flash + 1); #endif /* Funky AMD */ if ((flash_vendid == 1) && (flash_devid == 0x227e)) { /* Get real devid */ #ifdef MIPSEB flash_devid = *(flash+0xe); #else flash_devid = *(flash+0xf); #endif } flashutl_desc = flashes; while (flashutl_desc->mfgid != 0 && !(flashutl_desc->mfgid == flash_vendid && flashutl_desc->devid == flash_devid)) { flashutl_desc++; } if (flashutl_desc->mfgid != 0) break; flashutl_cmd = &flash_cmds[idx--]; } if (flashutl_desc->mfgid == 0) { flashutl_desc = NULL; flashutl_cmd = NULL; } else { flashutl_cmd = flash_cmds; while (flashutl_cmd->type != 0 && flashutl_cmd->type != flashutl_desc->type) flashutl_cmd++; if (flashutl_cmd->type == 0) flashutl_cmd = NULL; } if (flashutl_cmd != NULL) { flash_reset(); } if (flashutl_desc == NULL) { if (flash_str) sprintf(flash_str, "UNKNOWN 0x%x 0x%x", flash_vendid, flash_devid); DPRINT(("Flash type UNKNOWN\n")); return 1; } if (flash_str) strcpy(flash_str, flashutl_desc->desc); DPRINT(("Flash type \"%s\"\n", flashutl_desc->desc)); return 0; }