Esempio n. 1
0
static int cfi_chip_setup(struct map_info *map, 
		   struct cfi_private *cfi)
{
	int ofs_factor = cfi->interleave*cfi->device_type;
	__u32 base = 0;
	int num_erase_regions = cfi_read_query(map, base + (0x10 + 28)*ofs_factor);
	int i;

#ifdef DEBUG_CFI
	printk("Number of erase regions: %d\n", num_erase_regions);
#endif
	if (!num_erase_regions)
		return 0;

	cfi->cfiq = kmalloc(sizeof(struct cfi_ident) + num_erase_regions * 4, GFP_KERNEL);
	if (!cfi->cfiq) {
		printk(KERN_WARNING "%s: kmalloc failed for CFI ident structure\n", map->name);
		return 0;
	}
	
	memset(cfi->cfiq,0,sizeof(struct cfi_ident));	
	
	cfi->cfi_mode = CFI_MODE_CFI;
	cfi->fast_prog=1;		/* CFI supports fast programming */
	
	/* Read the CFI info structure */
	for (i=0; i<(sizeof(struct cfi_ident) + num_erase_regions * 4); i++) {
		((unsigned char *)cfi->cfiq)[i] = cfi_read_query(map,base + (0x10 + i)*ofs_factor);
	}
	
	/* Do any necessary byteswapping */
	cfi->cfiq->P_ID = le16_to_cpu(cfi->cfiq->P_ID);
	
	cfi->cfiq->P_ADR = le16_to_cpu(cfi->cfiq->P_ADR);
	cfi->cfiq->A_ID = le16_to_cpu(cfi->cfiq->A_ID);
	cfi->cfiq->A_ADR = le16_to_cpu(cfi->cfiq->A_ADR);
	cfi->cfiq->InterfaceDesc = le16_to_cpu(cfi->cfiq->InterfaceDesc);
	cfi->cfiq->MaxBufWriteSize = le16_to_cpu(cfi->cfiq->MaxBufWriteSize);

#ifdef DEBUG_CFI
	/* Dump the information therein */
	print_cfi_ident(cfi->cfiq);
#endif

	for (i=0; i<cfi->cfiq->NumEraseRegions; i++) {
		cfi->cfiq->EraseRegionInfo[i] = le32_to_cpu(cfi->cfiq->EraseRegionInfo[i]);
		
#ifdef DEBUG_CFI		
		printk("  Erase Region #%d: BlockSize 0x%4.4X bytes, %d blocks\n",
		       i, (cfi->cfiq->EraseRegionInfo[i] >> 8) & ~0xff, 
		       (cfi->cfiq->EraseRegionInfo[i] & 0xffff) + 1);
#endif
	}
	/* Put it back into Read Mode */
	cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);

	return 1;
}
Esempio n. 2
0
struct mtd_info *cfi_cmdset_0701(struct map_info *map, int primary)
{
	struct cfi_private *cfi = map->fldrv_priv;
	int ofs_factor = cfi->interleave * cfi->device_type;
	int i;
	__u8 major, minor;
	__u32 base = cfi->chips[0].start;

	if (cfi->cfi_mode==1){
		__u16 adr = primary?cfi->cfiq->P_ADR:cfi->cfiq->A_ADR;

		cfi_send_gen_cmd(0xAA, 0x5555, base, map, cfi, cfi->device_type, NULL);
		cfi_send_gen_cmd(0x55, 0x2AAA, base, map, cfi, cfi->device_type, NULL);
		cfi_send_gen_cmd(0x98, 0x5555, base, map, cfi, cfi->device_type, NULL);
		
		major = cfi_read_query(map, base + (adr+3)*ofs_factor);
		minor = cfi_read_query(map, base + (adr+4)*ofs_factor);
		
		printk(" SST Query Table v%c.%c at 0x%4.4X\n",
		       major, minor, adr);
		cfi_send_gen_cmd(0xf0, 0x5555, base, map, cfi, cfi->device_type, NULL);
		
		cfi_send_gen_cmd(0xAA, 0x5555, base, map, cfi, cfi->device_type, NULL);
		cfi_send_gen_cmd(0x55, 0x2AAA, base, map, cfi, cfi->device_type, NULL);
		cfi_send_gen_cmd(0x90, 0x5555, base, map, cfi, cfi->device_type, NULL);
		cfi->mfr = cfi_read_query(map, base);
		cfi->id = cfi_read_query(map, base + ofs_factor);

		cfi_send_gen_cmd(0xAA, 0x5555, base, map, cfi, cfi->device_type, NULL);
		cfi_send_gen_cmd(0x55, 0x2AAA, base, map, cfi, cfi->device_type, NULL);
		cfi_send_gen_cmd(0x98, 0x5555, base, map, cfi, cfi->device_type, NULL);
		
		switch (cfi->device_type) {
		case CFI_DEVICETYPE_X16:
			cfi->addr_unlock1 = 0x5555;
			cfi->addr_unlock2 = 0x2AAA;
			break;
		default:
			printk(KERN_NOTICE "Eep. Unknown cfi_cmdset_0701 device type %d\n", cfi->device_type);
			return NULL;
		}
	} /* CFI mode */

	for (i=0; i< cfi->numchips; i++) {
		cfi->chips[i].word_write_time = 1<<cfi->cfiq->WordWriteTimeoutTyp;
		cfi->chips[i].buffer_write_time = 1<<cfi->cfiq->BufWriteTimeoutTyp;
		cfi->chips[i].erase_time = 1<<cfi->cfiq->BlockEraseTimeoutTyp;
	}		
	
	map->fldrv = &cfi_sststd_chipdrv;
	MOD_INC_USE_COUNT;

	cfi_send_gen_cmd(0xf0, 0x5555, base, map, cfi, cfi->device_type, NULL);
	return cfi_sststd_setup(map);
}
Esempio n. 3
0
struct cfi_extquery *
cfi_read_pri(struct map_info *map, __u16 adr, __u16 size, const char* name)
{
	struct cfi_private *cfi = map->fldrv_priv;
	__u32 base = 0; // cfi->chips[0].start;
	int ofs_factor = cfi->interleave * cfi->device_type;
	int i;
	struct cfi_extquery *extp = NULL;

	printk(" %s Extended Query Table at 0x%4.4X\n", name, adr);
	if (!adr)
		goto out;

	/* Switch it into Query Mode */
	cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL);

	extp = kmalloc(size, GFP_KERNEL);
	if (!extp) {
		printk(KERN_ERR "Failed to allocate memory\n");
		goto out;
	}
		
	/* Read in the Extended Query Table */
	for (i=0; i<size; i++) {
		((unsigned char *)extp)[i] = 
			cfi_read_query(map, base+((adr+i)*ofs_factor));
	}

#ifndef CONFIG_BCM96348
	/* XXX: Some AMD flashes do not report the correct version (they 
	 * return zero instead).*/
	
	if (extp->MajorVersion != '1' || 
	    (extp->MinorVersion < '0' || extp->MinorVersion > '3')) {
		printk(KERN_WARNING "  Unknown %s Extended Query "
		       "version %c.%c.\n",  name, extp->MajorVersion,
		       extp->MinorVersion);
		kfree(extp);
		extp = NULL;
		goto out;
	}
#endif

out:
	/* Make sure it's in read mode */
	cfi_send_gen_cmd(0xf0, 0, base, map, cfi, cfi->device_type, NULL);
	cfi_send_gen_cmd(0xff, 0, base, map, cfi, cfi->device_type, NULL);

	return extp;
}
Esempio n. 4
0
static inline int cfi_isSST(struct map_info *map,struct cfi_private *cfi, __u32 base)
{
        int man_id;

	cfi_send_gen_cmd(0xAA, 0x5555, base, map, cfi, cfi->device_type, NULL);
        cfi_send_gen_cmd(0x55, 0x2AAA, base, map, cfi, cfi->device_type, NULL);
        cfi_send_gen_cmd(0x90, 0x5555, base, map, cfi, cfi->device_type, NULL);
        man_id = cfi_read_query(map, base);

	/* SST manufacture id = 0xBF */
        if(man_id==0xBF){
                return 1;
        }else{
                return 0;
        }

}
Esempio n. 5
0
__xipram cfi_read_pri(struct map_info *map, __u16 adr, __u16 size, const char* name)
{
	struct cfi_private *cfi = map->fldrv_priv;
	__u32 base = 0; // cfi->chips[0].start;
	int ofs_factor = cfi->interleave * cfi->device_type;
	int i;
	struct cfi_extquery *extp = NULL;

	if (!adr)
		goto out;

	printk(KERN_INFO "%s Extended Query Table at 0x%4.4X\n", name, adr);

	extp = kmalloc(size, GFP_KERNEL);
	if (!extp) {
		printk(KERN_ERR "Failed to allocate memory\n");
		goto out;
	}

#ifdef CONFIG_MTD_XIP
	local_irq_disable();
#endif

	/* Switch it into Query Mode */
	cfi_qry_mode_on(base, map, cfi);
	/* Read in the Extended Query Table */
	for (i=0; i<size; i++) {
		((unsigned char *)extp)[i] =
			cfi_read_query(map, base+((adr+i)*ofs_factor));
	}

	/* Make sure it returns to read mode */
	cfi_qry_mode_off(base, map, cfi);

#ifdef CONFIG_MTD_XIP
	(void) map_read(map, base);
	xip_iprefetch();
	local_irq_enable();
#endif

 out:	return extp;
}
Esempio n. 6
0
static int cfi_chip_setup(struct map_info *map,
                          struct cfi_private *cfi)
{
    int ofs_factor = cfi->interleave*cfi->device_type;
    __u32 base = 0;
    int num_erase_regions = cfi_read_query(map, base + (0x10 + 28)*ofs_factor);
    int i;

#ifdef DEBUG_CFI
    printk("Number of erase regions: %d\n", num_erase_regions);
#endif
    if (!num_erase_regions)
        return 0;

    cfi->cfiq = kmalloc(sizeof(struct cfi_ident) + num_erase_regions * 4, GFP_KERNEL);
    if (!cfi->cfiq) {
        printk(KERN_WARNING "%s: kmalloc failed for CFI ident structure\n", map->name);
        return 0;
    }

    memset(cfi->cfiq,0,sizeof(struct cfi_ident));

    cfi->cfi_mode = CFI_MODE_CFI;
    cfi->fast_prog=1;		/* CFI supports fast programming */

    /* Read the CFI info structure */
    for (i=0; i<(sizeof(struct cfi_ident) + num_erase_regions * 4); i++) {
        ((unsigned char *)cfi->cfiq)[i] = cfi_read_query(map,base + (0x10 + i)*ofs_factor);
    }

    /* Do any necessary byteswapping */
    cfi->cfiq->P_ID = le16_to_cpu(cfi->cfiq->P_ID);

    cfi->cfiq->P_ADR = le16_to_cpu(cfi->cfiq->P_ADR);
    cfi->cfiq->A_ID = le16_to_cpu(cfi->cfiq->A_ID);
    cfi->cfiq->A_ADR = le16_to_cpu(cfi->cfiq->A_ADR);
    cfi->cfiq->InterfaceDesc = le16_to_cpu(cfi->cfiq->InterfaceDesc);
    cfi->cfiq->MaxBufWriteSize = le16_to_cpu(cfi->cfiq->MaxBufWriteSize);

    /*
     * ST screwed up the CFI interface for buffer writes on their parts,
     * so this needs to be fixed up by hand here.
         *
         * A possible enhancment is that instead of just reverting back
         * to word write (as this does), we could use the ST specific double
         * word write instead.
     */

    if (cfi_read_query(map,base) == 0x20) {
        cfi->cfiq->BufWriteTimeoutTyp = 0;
        cfi->cfiq->BufWriteTimeoutMax = 0;
    }

#ifdef DEBUG_CFI
    /* Dump the information therein */
    print_cfi_ident(cfi->cfiq);
#endif

    for (i=0; i<cfi->cfiq->NumEraseRegions; i++) {
        cfi->cfiq->EraseRegionInfo[i] = le32_to_cpu(cfi->cfiq->EraseRegionInfo[i]);

#ifdef DEBUG_CFI
        printk("  Erase Region #%d: BlockSize 0x%4.4X bytes, %d blocks\n",
               i, (cfi->cfiq->EraseRegionInfo[i] >> 8) & ~0xff,
               (cfi->cfiq->EraseRegionInfo[i] & 0xffff) + 1);
#endif
    }
    /* Put it back into Read Mode */
    cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);

    /* some devices don't respond to 0xF0, so send 0xFF to be sure */
    cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);

    return 1;
}
struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary)
{
	struct cfi_private *cfi = map->fldrv_priv;
	unsigned char bootloc;
	int ofs_factor = cfi->interleave * cfi->device_type;
	int i;
	__u8 major, minor;
	__u32 base = cfi->chips[0].start;

	if (cfi->cfi_mode==CFI_MODE_CFI){
		__u16 adr = primary?cfi->cfiq->P_ADR:cfi->cfiq->A_ADR;

		cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL);
		
		major = cfi_read_query(map, base + (adr+3)*ofs_factor);
		minor = cfi_read_query(map, base + (adr+4)*ofs_factor);
		
		printk(KERN_NOTICE " Amd/Fujitsu Extended Query Table v%c.%c at 0x%4.4X\n",
		       major, minor, adr);
				cfi_send_gen_cmd(0xf0, 0x55, base, map, cfi, cfi->device_type, NULL);
		
		cfi_send_gen_cmd(0xaa, 0x555, base, map, cfi, cfi->device_type, NULL);
		cfi_send_gen_cmd(0x55, 0x2aa, base, map, cfi, cfi->device_type, NULL);
		cfi_send_gen_cmd(0x90, 0x555, base, map, cfi, cfi->device_type, NULL);
		cfi->mfr = cfi_read_query(map, base);
		cfi->id = cfi_read_query(map, base + ofs_factor);    

		/* Wheee. Bring me the head of someone at AMD. */
#ifdef AMD_BOOTLOC_BUG
		if (((major << 8) | minor) < 0x3131) {
			/* CFI version 1.0 => don't trust bootloc */
			if (cfi->id & 0x80) {
				printk(KERN_WARNING "%s: JEDEC Device ID is 0x%02X. Assuming broken CFI table.\n", map->name, cfi->id);
				bootloc = 3;	/* top boot */
			} else {
				bootloc = 2;	/* bottom boot */
			}
		} else
#endif
			{
				cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL);
				bootloc = cfi_read_query(map, base + (adr+15)*ofs_factor);
			}
		if (bootloc == 3 && cfi->cfiq->NumEraseRegions > 1) {
			printk(KERN_WARNING "%s: Swapping erase regions for broken CFI table.\n", map->name);
			
			for (i=0; i<cfi->cfiq->NumEraseRegions / 2; i++) {
				int j = (cfi->cfiq->NumEraseRegions-1)-i;
				__u32 swap;
				
				swap = cfi->cfiq->EraseRegionInfo[i];
				cfi->cfiq->EraseRegionInfo[i] = cfi->cfiq->EraseRegionInfo[j];
				cfi->cfiq->EraseRegionInfo[j] = swap;
			}
		}
		switch (cfi->device_type) {
		case CFI_DEVICETYPE_X8:
			cfi->addr_unlock1 = 0x555; 
			cfi->addr_unlock2 = 0x2aa; 
			break;
		case CFI_DEVICETYPE_X16:
			cfi->addr_unlock1 = 0xaaa;
			if (map->buswidth == cfi->interleave) {
				/* X16 chip(s) in X8 mode */
				cfi->addr_unlock2 = 0x555;
			} else {
				cfi->addr_unlock2 = 0x554;
			}
			break;
		case CFI_DEVICETYPE_X32:
			cfi->addr_unlock2 = 0xaaa; 
			if (map->buswidth == cfi->interleave) {
                        	cfi->addr_unlock1 = 0x1555;
			} else {
				cfi->addr_unlock1 = 0x1554;
			}
			break;
		default:
			printk(KERN_NOTICE "Eep. Unknown cfi_cmdset_0002 device type %d\n", cfi->device_type);
			return NULL;
		}
	} /* CFI mode */

	for (i=0; i< cfi->numchips; i++) {
		cfi->chips[i].word_write_time = 1<<cfi->cfiq->WordWriteTimeoutTyp;
		cfi->chips[i].buffer_write_time = 1<<cfi->cfiq->BufWriteTimeoutTyp;
		cfi->chips[i].erase_time = 1<<cfi->cfiq->BlockEraseTimeoutTyp;
	}		
	
	map->fldrv = &cfi_amdstd_chipdrv;

	cfi_send_gen_cmd(0xf0, 0x55, base, map, cfi, cfi->device_type, NULL);
	return cfi_amdstd_setup(map);
}