📄 flash.c
字号:
/************************************************************************* Include files************************************************************************/#include <linux/types.h>#include <linux/errno.h>#include <linux/slab.h>#include <linux/miscdevice.h>#include <linux/module.h>#include <linux/init.h>#include <linux/ctype.h>#include <asm/uaccess.h>#include <asm/system.h>#include <asm/page.h>#include <asm/io.h>#include <linux/vmalloc.h>#include <linux/mm.h>#include <linux/wrapper.h>#include <linux/version.h>#include <linux/delay.h>#include "flash.h"#define MAJOR_NUM 222#define DRIVER_NAME "flash"static int cnt_open=0;unsigned char *flash_mem;//define kernel size 1.25Mbyte#define KERNEL_SIZE 0x100000#define KERNEL_BASE 0x81000000#define FLASH_BASE 0xBF800000#define FLASH_END 0xBFBFFFFF#define ERASE_FLASH 0#define READ_FLASH 1#define WRITE_FLASH 2#define UUPDATE_FLASH 3#define FLASH_16BIT#define ADDR0 0x555#define ADDR1 0x2aa#define FLASH_WORD_SIZE unsigned shorttypedef unsigned char UINT8;typedef signed char INT8;typedef unsigned short UINT16;typedef signed short INT16;typedef unsigned int UINT32;typedef signed int INT32;#define KSEG_MSK 0xE0000000#define KSEG1BASE 0xA0000000#define iKSEG1(addr) (((UINT32)(addr) & ~KSEG_MSK) | KSEG1BASE)struct ioctl { unsigned int addr; unsigned int data;}; flash_info_t flash_info[1];static void * rvmalloc(unsigned long size){ void * mem; unsigned long adr; size=PAGE_ALIGN(size); mem=vmalloc_32(size); if (mem) { memset(mem, 0, size); adr=(unsigned long) mem; while (size > 0) { mem_map_reserve(vmalloc_to_page((void *)adr)); adr+=PAGE_SIZE; size-=PAGE_SIZE; } } return mem;}static void rvfree(void * mem, unsigned long size){ unsigned long adr,siz=size; if (mem) { adr=(unsigned long) mem; while ( siz > 0) { mem_map_unreserve(vmalloc_to_page((void *)adr)); adr+=PAGE_SIZE; siz-=PAGE_SIZE; } vfree(mem); }}static ulong flash_get_size (vu_long *addr, flash_info_t *info){ short i,n; FLASH_WORD_SIZE value,value1; ulong base = (ulong)addr; volatile FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *)addr; /* Write auto select command: read Manufacturer ID */ addr2[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA; udelay(100); addr2[ADDR1] = (FLASH_WORD_SIZE)0x00550055; udelay(100); addr2[ADDR0] = (FLASH_WORD_SIZE)0x00900090; udelay(100); value = addr2[0];// printk(KERN_INFO "########First ManuD : 0x%04x########\n", value); switch (value) { case (FLASH_WORD_SIZE)AMD_MANUFACT: info->flash_id = FLASH_MAN_AMD; break; case (FLASH_WORD_SIZE)MX_MANUFACT: info->flash_id = FLASH_MAN_MX; break; case (FLASH_WORD_SIZE)FUJ_MANUFACT: info->flash_id = FLASH_MAN_FUJ; break; default: /* Write auto select command: read Manufacturer ID */ /*Detect for FUJ_FLASH*/ udelay(100); addr2[0x5555] = (FLASH_WORD_SIZE)0x00AA00AA; udelay(100); addr2[0x2aaa] = (FLASH_WORD_SIZE)0x00550055; udelay(100); addr2[0x5555] = (FLASH_WORD_SIZE)0x00900090; udelay(100); value = addr2[0];// printk("########Re-read ManuD : 0x%04x########\n", value); if(value==(FLASH_WORD_SIZE)FUJ_MANUFACT) { info->flash_id = FLASH_MAN_FUJ; break; } else { info->flash_id = FLASH_UNKNOWN; info->sector_count = 0; info->size = 0; return (0); /* no or unknown flash */ } break; } udelay(100); value = addr2[1]; /* device ID *///printk(KERN_INFO "########DeviceID : 0x%08x########\n", value); switch (value) { case (FLASH_WORD_SIZE)FUJI_ID_29LV650UE: info->flash_id += FLASH_FUJLV650; info->sector_count = 128; info->size = 0x00800000; break; /* => 8 MB */ case (FLASH_WORD_SIZE)MX_ID_LV640T: info->flash_id += FLASH_MX29LV640T; info->sector_count = 135; info->size = 0x00800000; break; case (FLASH_WORD_SIZE)MX_ID_LV640B: info->flash_id += FLASH_MX29LV640B; info->sector_count = 135; info->size = 0x00800000; break; case (FLASH_WORD_SIZE)AMD_ID_DL640: udelay(100); value1=addr2[0x0e]; // printk(KERN_INFO "########DeviceID sub1: 0x%08x########\n", value1); if(value1==0x2202) { info->flash_id += FLASH_AMDL640; info->sector_count = 142; info->size = 0x00800000; } else if(value1==0x2210) { info->flash_id += FLASH_S29GL064; info->sector_count = 135; info->size = 0x00800000; } else { info->flash_id = FLASH_UNKNOWN; return (0); /* => no or unknown flash */ } break; /* => 8 MB */ default: info->flash_id = FLASH_UNKNOWN; return (0); /* => no or unknown flash */ } /* set up sector start address table */ if (((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) || (info->flash_id == FLASH_AM040)) { for (i = 0; i < info->sector_count; i++) info->start[i] = base + (i * 0x00010000); } else if((info->flash_id & FLASH_TYPEMASK) ==FLASH_AMDL640) { /* set sector offsets for dual boot block type */// printk(KERN_INFO "########AM29DL640 offset########\n"); for (i=0; i<8; ++i) { /* 8 x 8k boot sectors */ info->start[i] = base; base += 8 << 10; } n = info->sector_count - 8; while (i < n) { /* 64k regular sectors */ info->start[i] = base; base += 64 << 10; ++i; } while (i < info->sector_count) { /* 8 x 8k boot sectors */ info->start[i] = base; base += 8 << 10; ++i; } } else if(((info->flash_id & FLASH_TYPEMASK) ==FLASH_S29GL064)||((info->flash_id & FLASH_TYPEMASK) ==FLASH_MX29LV640T)) { /* set sector offsets for top boot block type */// printk(KERN_INFO "########MX29lv640T S29GL064R3 offset########\n"); i=0; n = info->sector_count - 8; while (i < n) { /* 64k regular sectors */ info->start[i] = base; base += 64 << 10; ++i; } while (i < info->sector_count) { /* 8 x 8k boot sectors */ info->start[i] = base; base += 8 << 10; ++i; } } else if((info->flash_id & FLASH_TYPEMASK) ==FLASH_MX29LV640B) { /* set sector offsets for bottom boot block type */ // printk(KERN_INFO "########MX29lv640B offset########\n"); i=0; for (i=0; i<8; ++i) { /* 8 x 8k boot sectors */ info->start[i] = base; base += 8 << 10; } while (i < info->sector_count) { /* 64k regular sectors */ info->start[i] = base; base += 64 << 10; ++i; } } else { if (info->flash_id & FLASH_BTYPE) { /* set sector offsets for bottom boot block type */ info->start[0] = base + 0x00000000; info->start[1] = base + 0x00004000; info->start[2] = base + 0x00006000; info->start[3] = base + 0x00008000; for (i = 4; i < info->sector_count; i++) { info->start[i] = base + (i * 0x00010000) - 0x00030000; } } else { /* set sector offsets for top boot block type */ i = info->sector_count - 1; info->start[i--] = base + info->size - 0x00004000; info->start[i--] = base + info->size - 0x00006000; info->start[i--] = base + info->size - 0x00008000; for (; i >= 0; i--) { info->start[i] = base + i * 0x00010000; } } } /* check for protected sectors */ for (i = 0; i < info->sector_count; i++) { info->protect[i] =0; } /* * Prevent writes to uninitialized FLASH. */ addr2 = (FLASH_WORD_SIZE *)info->start[0]; *addr2 = (FLASH_WORD_SIZE)0x00F000F0; /* reset bank */ return (info->size);}static void flash_get_offsets (ulong base, flash_info_t *info){ int i,n; /* set up sector start address table */ if (((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) || (info->flash_id == FLASH_AM040)){ for (i = 0; i < info->sector_count; i++) info->start[i] = base + (i * 0x00010000); } else if((info->flash_id & FLASH_TYPEMASK) ==FLASH_AMDL640) { /* set sector offsets for dual boot block type */ for (i=0; i<8; ++i) { /* 8 x 8k boot sectors */ info->start[i] = base; base += 8 << 10; } n = info->sector_count - 8; while (i < n) { /* 64k regular sectors */ info->start[i] = base; base += 64 << 10; ++i; } while (i < info->sector_count) { /* 8 x 8k boot sectors */ info->start[i] = base; base += 8 << 10; ++i; } } else if(((info->flash_id & FLASH_TYPEMASK) ==FLASH_S29GL064)||((info->flash_id & FLASH_TYPEMASK) ==FLASH_MX29LV640T)) { /* set sector offsets for top boot block type */// printk(KERN_INFO "########MX29lv640T S29GL064R3 offset########\n"); i=0; n = info->sector_count - 8; while (i < n) { /* 64k regular sectors */ info->start[i] = base; base += 64 << 10; ++i; } while (i < info->sector_count) { /* 8 x 8k boot sectors */ info->start[i] = base; base += 8 << 10; ++i; } } else if((info->flash_id & FLASH_TYPEMASK) ==FLASH_MX29LV640B) { /* set sector offsets for bottom boot block type */// printk(KERN_INFO "########MX29lv640B offset########\n"); i=0; for (i=0; i<8; ++i) { /* 8 x 8k boot sectors */ info->start[i] = base; base += 8 << 10; } while (i < info->sector_count) { /* 64k regular sectors */ info->start[i] = base; base += 64 << 10; ++i; } } else { if (info->flash_id & FLASH_BTYPE) { /* set sector offsets for bottom boot block type */ info->start[0] = base + 0x00000000; info->start[1] = base + 0x00004000; info->start[2] = base + 0x00006000; info->start[3] = base + 0x00008000; for (i = 4; i < info->sector_count; i++) { info->start[i] = base + (i * 0x00010000) - 0x00030000; } } else { /* set sector offsets for top boot block type */ i = info->sector_count - 1; for (; i >= 0; i--) { info->start[i] = base + i * 0x00010000; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -