Ejemplo n.º 1
0
/* Probe for NVRAM header */
static int
early_nvram_init(void)
{
	struct nvram_header *header;
	chipcregs_t *cc;
	struct sflash *info = NULL;
	int i;
	uint32 base, off, lim;
	u32 *src, *dst;
	uint32 fltype;
#ifdef NFLASH_SUPPORT
	struct nflash *nfl_info = NULL;
	uint32 blocksize;
#endif
	header = (struct nvram_header *)ram_nvram_buf;

	if ((cc = si_setcore(sih, CC_CORE_ID, 0)) != NULL) {
#ifdef NFLASH_SUPPORT
		if ((sih->ccrev == 38) && ((sih->chipst & (1 << 4)) != 0)) {
			fltype = NFLASH;
			base = KSEG1ADDR(SI_FLASH1);
		} else
#endif
		{
			fltype = readl(&cc->capabilities) & CC_CAP_FLASH_MASK;
			base = KSEG1ADDR(SI_FLASH2);
		}
		switch (fltype) {
		case PFLASH:
			lim = SI_FLASH2_SZ;
			break;

		case SFLASH_ST:
		case SFLASH_AT:
			if ((info = sflash_init(sih, cc)) == NULL)
				return -1;
			lim = info->size;
			break;
#ifdef NFLASH_SUPPORT
		case NFLASH:
			if ((nfl_info = nflash_init(sih, cc)) == NULL)
				return -1;
			lim = SI_FLASH1_SZ;
			break;
#endif
		case FLASH_NONE:
		default:
			return -1;
		}
	} else {
		/* extif assumed, Stop at 4 MB */
		base = KSEG1ADDR(SI_FLASH1);
		lim = SI_FLASH1_SZ;
	}
#ifdef NFLASH_SUPPORT
	if (nfl_info != NULL) {
		blocksize = nfl_info->blocksize;
		off = blocksize;
		while (off <= lim) {
			if (nflash_checkbadb(sih, cc, off) != 0) {
				off += blocksize;
				continue;
			}
			header = (struct nvram_header *) KSEG1ADDR(base + off);
			if (header->magic == NVRAM_MAGIC)
				if (nvram_calc_crc(header) == (uint8) header->crc_ver_init) {
					goto found;
				}
			off += blocksize;
		}
	} else
#endif
	off = FLASH_MIN;

#ifdef RTN66U_NVRAM_64K_SUPPORT
	header = (struct nvram_header *) KSEG1ADDR(base + lim - 0x8000);
	if(header->magic==0xffffffff) {
        	header = (struct nvram_header *) KSEG1ADDR(base + 1 KB);
	        if (nvram_valid(header))
        	        goto found;
	}
#endif

	while (off <= lim) {
		/* Windowed flash access */
		header = (struct nvram_header *) KSEG1ADDR(base + off - NVRAM_SPACE);
		if (nvram_valid(header))
			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 (nvram_valid(header))
		goto found;
	header = (struct nvram_header *) KSEG1ADDR(base + 1 KB);
	if (nvram_valid(header))
		goto found;

	return -1;

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++);

	return 0;
}
Ejemplo n.º 2
0
/* 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.
	 */
	sih = si_kattach(SI_OSH);
	ASSERT(sih);

	osh = si_osh(sih);

	cc = (chipcregs_t *)si_setcoreidx(sih, SI_CC_IDX);
	ASSERT(cc);

	flashutl_base = (void *)OSL_UNCACHED((uintptr)SI_FLASH2);
	/* Select SFLASH ? */
	fltype = R_REG(osh, &cc->capabilities) & CC_CAP_FLASH_MASK;
	if (fltype == SFLASH_ST || fltype == SFLASH_AT) {
		if (sih->ccrev == 12)
			flashutl_base = (void *)OSL_UNCACHED((uintptr)SI_FLASH2);
		else
			flashutl_base = (void *)OSL_CACHED((uintptr)SI_FLASH2);
		sflash = sflash_init(sih, 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_wsz = (R_REG(osh, &cc->flash_config) & CC_CFG_DS) ? sizeof(uint16) : sizeof(uint8);
	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);
			/* Delay for turn around time */
			OSL_DELAY(1);
		}

#ifdef MIPSEB
#ifdef	BCMHND74K
		flash_vendid = flash_readword(FLASH_ADDR(0)^6);
		flash_devid = flash_readword(FLASH_ADDR(2)^6);
#else	/* !74K, bcm33xx */
		flash_vendid = flash_readword(FLASH_ADDR(2));
		flash_devid = flash_readword(FLASH_ADDR(0));
#endif	/* BCMHND74K */
#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 && flashutl_wsz == sizeof(uint16)) ||
		        (flash_devid == 0x7e && flashutl_wsz == sizeof(uint8)))) {
			/* Get real devid */
			uint16 flash_devid_5th;
#ifdef MIPSEB
#ifdef	BCMHND74K
			flash_devid_5th = flash_readword(FLASH_ADDR(0x1c)^6) << 8;
			flash_devid = (flash_readword(FLASH_ADDR(0x1e)^6) & 0xff) | flash_devid_5th;
#else	/* !74K, bcm33xx */
			flash_devid_5th = flash_readword(FLASH_ADDR(0x1e)) << 8;
			flash_devid = (flash_readword(FLASH_ADDR(0x1c)) & 0xff) | flash_devid_5th;
#endif	/* BCMHND74K */
#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;
}
Ejemplo n.º 3
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++);
}
Ejemplo n.º 4
0
int
flashDrvLibInit(void)
{
    FLASH_TYPES     dev;
    FLASH_VENDORS   vendor;
    int i;
    uint32 fltype = PFLASH;
    osl_t *osh;
    struct sflash *sflash;
    
    if (flashDrvInitialized)
	    return (OK);

    flashBaseAddress = FLASH_BASE_ADDRESS_ALIAS;

    /*
     * Check for serial flash.
     */
    sih = si_kattach(SI_OSH);
    ASSERT(sih);
    
    osh = si_osh(sih);
    
    cc = (chipcregs_t *)si_setcoreidx(sih, SI_CC_IDX);
    ASSERT(cc);

    /* Select SFLASH */
    fltype = R_REG(osh, &cc->capabilities) & CC_CAP_FLASH_MASK;
    if (fltype == SFLASH_ST || fltype == SFLASH_AT) {
        sflash = sflash_init(sih, cc);

        if (sflash == NULL) {
            printf("flashInit(): Unrecognized Device (SFLASH)\n");
            return (ERROR);
        }
        flashDrvFuncs = &flashsflash;
        flashDrvFuncs->flashAutoSelect(&dev, &vendor);

        flashSectorCount = sflash->numblocks;
        flashDevSectorSize = sflash->blocksize;

        if (flashVerbose) {
            printf("flashInit(): SFLASH Found\n");
        }
    } else {
        flashDrvFuncs = &flashs29gl256p;
        flashDrvFuncs->flashAutoSelect(&dev, &vendor);
        if ((vendor == 0xFF) && (dev == 0xFF)) {
            flashDrvFuncs = &flash29gl128;
            flashDrvFuncs->flashAutoSelect(&dev, &vendor);
        }
    
        if ((vendor == 0xFF) && (dev == 0xFF)) {
            flashDrvFuncs = &flash29l640;
            flashDrvFuncs->flashAutoSelect(&dev, &vendor);
        }
        if ((vendor == 0xFF) && (dev == 0xFF)) {
            flashDrvFuncs = &flash29l320;
            flashDrvFuncs->flashAutoSelect(&dev, &vendor);
        }
        if ((vendor == 0xFF) && (dev == 0xFF)) {
            flashDrvFuncs = &flash29l160;
            flashDrvFuncs->flashAutoSelect(&dev, &vendor);
        }
        if ((vendor == 0xFF) && (dev == 0xFF)) {
            flashDrvFuncs = &flash28f320;
            flashDrvFuncs->flashAutoSelect(&dev, &vendor);
        }
    
        switch (vendor) {
            case AMD:
            case ALLIANCE:
            case MXIC:
            switch (dev) {
                case FLASH_2F040:
                    flashSectorCount = 8;
                    flashDevSectorSize = 0x10000;
                    if (flashVerbose)
                        printf("flashInit(): 2F040 Found\n");
                    break;
                case FLASH_2F080:
                    flashSectorCount = 16;
                    flashDevSectorSize = 0x10000;
                    if (flashVerbose)
                        printf("flashInit(): 2F080 Found\n");
                    break;
    
                case FLASH_2L081:
                    flashSectorCount = 16;
                    flashDevSectorSize = 0x10000;
                    if (flashVerbose)
                        printf("flashInit(): 29LV081B Found\n");
                    break;
    
                case FLASH_2L160:
                case FLASH_2L017:
                    flashSectorCount = 32;
                    flashDevSectorSize = 0x10000;
                    if (flashVerbose)
                        printf("flashInit(): 29LV160D Found\n");
                    break;
    
                case FLASH_2L640:
                case FLASH_MX2L640:
                    flashSectorCount = 128;
                    flashDevSectorSize = 0x10000;
                    if (flashVerbose)
                        printf("flashInit(): 29LV640M Found\n");
                    break;
    
                case FLASH_29GL128:
                    /* Spansion 29GL128 is physically 128 sector count
                     * To make flash support backward compatible to old device,
                     * only use 64 for 8MB */
                    flashSectorCount = 64;
                    flashDevSectorSize = 0x20000;
                    if (flashVerbose)
                        printf("flashInit(): 29GL128 Found\n");
                    break;
    
                case FLASH_2L320:
                    flashSectorCount = 64;
                    flashDevSectorSize = 0x10000;
                    if (flashVerbose)
                        printf("flashInit(): 29LV320D Found\n");
                    break;
    
                case FLASH_S29GL128P:
                    flashSectorCount = 128;
                    flashDevSectorSize = 0x20000;
                    if (flashVerbose)
                        printf("flashInit(): FLASH_S29GL128P Found\n");
                    break;
    
                case FLASH_S29GL256P:
                    flashSectorCount = 256;
                    flashDevSectorSize = 0x20000;
                    if (flashVerbose)
                        printf("flashInit(): S29GL256P Found\n");
                    break;
    
                case FLASH_S29GL512P:
                    flashSectorCount = 512;
                    flashDevSectorSize = 0x20000;
                    if (flashVerbose)
                        printf("flashInit(): FLASH_S29GL512P Found\n");
                    break;
                    
                case FLASH_S29GL01GP:
                    flashSectorCount = 1024;
                    flashDevSectorSize = 0x20000;
                    if (flashVerbose)
                        printf("flashInit(): FLASH_S29GL01GP Found\n");
                    break;
    
                default:
                    printf("flashInit(): Unrecognized Device (0x%02X)\n", dev);
                    return (ERROR);
            }
            break;
    
            case INTEL:
            switch (dev) {
                case FLASH_2F320:
                    flashSectorCount = 32;
                    flashDevSectorSize = 0x20000;
                    if (flashVerbose)
                        printf("flashInit(): 28F320 Found\n");
                    break;
    
                default:
                    printf("flashInit(): Unrecognized Device (0x%02X)\n", dev);
                    return (ERROR);
            }
            break;
            default:
                printf("flashInit(): Unrecognized Vendor (0x%02X)\n", vendor);
                return (ERROR);
        }
    }
    flashSize = flashDevSectorSize * flashSectorCount;

    for (i = 0; i < TOTAL_LOADED_SECS; i++) {
        flashLoadedSectors[i].buffer = malloc(FLASH_SECTOR_SIZE);
        if (flashLoadedSectors[i].buffer == NULL) {
            printf("flashInit(): malloc() failed\n");
            for (; i > 0; i--) {
                free(flashLoadedSectors[i-1].buffer);
            }
            return (ERROR);
        }
        flashLoadedSectors[i].sector = -1;
        flashLoadedSectors[i].dirty = 0;
        flashLoadedSectors[i].fsSemID =
            semMCreate (SEM_Q_PRIORITY | SEM_DELETE_SAFE);
    }
    flashDrvInitialized ++;

    return (OK);
}
Ejemplo n.º 5
0
mod_init_t
sflash_mtd_init(void)
{
	struct pci_dev *pdev;
	int ret = 0;
	struct sflash *info;
	uint i;
#ifdef CONFIG_MTD_PARTITIONS
	struct mtd_partition *parts;
#endif

	if (!(pdev = pci_find_device(VENDOR_BROADCOM, SB_CC, NULL))) {
		printk(KERN_ERR "sflash: chipcommon not found\n");
		return -ENODEV;
	}

	memset(&sflash, 0, sizeof(struct sflash_mtd));
	init_MUTEX(&sflash.lock);

	/* attach to the backplane */
	if (!(sflash.sbh = sb_kattach(SB_OSH))) {
		printk(KERN_ERR "sflash: error attaching to backplane\n");
		ret = -EIO;
		goto fail;
	}

	/* Map registers and flash base */
	if (!(sflash.cc = ioremap_nocache(pci_resource_start(pdev, 0),
					  pci_resource_len(pdev, 0)))) {
		printk(KERN_ERR "sflash: error mapping registers\n");
		ret = -EIO;
		goto fail;
	}

	/* Initialize serial flash access */
	if (!(info = sflash_init(sflash.sbh, sflash.cc))) {
		printk(KERN_ERR "sflash: found no supported devices\n");
		ret = -ENODEV;
		goto fail;
	}

	printk(KERN_INFO "sflash: found serial flash; blocksize=%dKB, numblocks=%d, size=%dKB\n",info->blocksize/1024,info->numblocks,info->size/1024);

	/* Setup region info */
	sflash.region.offset = 0;
	sflash.region.erasesize = info->blocksize;
	sflash.region.numblocks = info->numblocks;
	if (sflash.region.erasesize > sflash.mtd.erasesize)
		sflash.mtd.erasesize = sflash.region.erasesize;
	sflash.mtd.size = info->size;
	sflash.mtd.numeraseregions = 1;

	/* Register with MTD */
	sflash.mtd.name = "sflash";
	sflash.mtd.type = MTD_NORFLASH;
	sflash.mtd.flags = MTD_CAP_NORFLASH;
	sflash.mtd.eraseregions = &sflash.region;
	sflash.mtd.module = THIS_MODULE;
	sflash.mtd.erase = sflash_mtd_erase;
	sflash.mtd.read = sflash_mtd_read;
	sflash.mtd.write = sflash_mtd_write;
	sflash.mtd.priv = &sflash;

#ifdef CONFIG_MTD_PARTITIONS
	parts = init_mtd_partitions(&sflash.mtd, sflash.mtd.size);
	for (i = 0; parts[i].name; i++);
	ret = add_mtd_partitions(&sflash.mtd, parts, i);
#else
	ret = add_mtd_device(&sflash.mtd);
#endif
	if (ret) {
		printk(KERN_ERR "sflash: add_mtd failed\n");
		goto fail;
	}

	return 0;

 fail:
	if (sflash.cc)
		iounmap((void *) sflash.cc);
	if (sflash.sbh)
		sb_detach(sflash.sbh);
	return ret;
}
Ejemplo n.º 6
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;
}
Ejemplo n.º 7
0
/* Probe for NVRAM header */
static int
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 = si_setcore(sih, CC_CORE_ID, 0)) != NULL) {
		base = KSEG1ADDR(SI_FLASH2);
		switch (readl(&cc->capabilities) & CC_CAP_FLASH_MASK) {
		case PFLASH:
			lim = SI_FLASH2_SZ;
			break;

		case SFLASH_ST:
		case SFLASH_AT:
			if ((info = sflash_init(sih, cc)) == NULL)
				return -1;
			lim = info->size;
			break;

		case FLASH_NONE:
		default:
			return -1;
		}
	} else {
		/* extif assumed, Stop at 4 MB */
		base = KSEG1ADDR(SI_FLASH1);
		lim = SI_FLASH1_SZ;
	}

	off = FLASH_MIN;
	while (off <= lim) {
		/* Windowed flash access */
		header = (struct nvram_header *) KSEG1ADDR(base + off - NVRAM_SPACE);
		if (header->magic == NVRAM_MAGIC)
			if (nvram_calc_crc(header) == (uint8) header->crc_ver_init) {
				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)
		if (nvram_calc_crc(header) == (uint8) header->crc_ver_init) {
			goto found;
		}

	header = (struct nvram_header *) KSEG1ADDR(base + 1 KB);
	if (header->magic == NVRAM_MAGIC)
		if (nvram_calc_crc(header) == (uint8) header->crc_ver_init) {
			goto found;
		}

	return -1;

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++);

	return 0;
}