免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1311 | 回复: 0
打印 上一主题 下一主题

Sumary of Flash Partitions [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2006-03-20 15:21 |只看该作者 |倒序浏览

All are simple indeed.You just create mtd_partition, map_info(implements all functions),call do_map_probe(type,map_info) which will return struct mtd_info。Then call add_mtd_partitions(struct mtd_info *, struct mtd_partition *, int) to add partitions。
Ok,that's all..
for more details ,you can read the files s3c2410_llg.c and physmap.c under the directory /drivers/mtd/maps..

#include
/* Partition definition structure:
*
* An array of struct partition is passed along with a MTD object to
* add_mtd_partitions() to create them.
* For each partition, these fields are available:
* name: string that will be used to label the partition's MTD device.
* size: the partition size; if defined as MTDPART_SIZ_FULL, the partition
*     will extend to the end of the master MTD device.
* offset: absolute starting position within the master MTD device; if
*     defined as MTDPART_OFS_APPEND, the partition will start where the              previous one ended; if MTDPART_OFS_NXTBLK, at the next erase block.
* mask_flags: contains flags that have to be masked (removed) from the
*     master MTD flag set for the corresponding MTD partition.
*      For example, to force a read-only partition, simply adding MTD_WRITEABLE to the mask_flags will do the trick.
*
* Note: writeable partitions require their size and offset be
* erasesize aligned (e.g. use MTDPART_OFS_NEXTBLK).
*/

struct mtd_partition {
    char *name;     /* identifier string */
    u_int32_t size;     /* partition size */
    u_int32_t offset;       /* offset within the master MTD space */
    u_int32_t mask_flags;   /* master MTD flags to mask out for this partition */
    struct mtd_info **mtdp; /* pointer to store the MTD object */
}
#define MTDPART_OFS_NXTBLK  (-2)
#define MTDPART_OFS_APPEND  (-1)
#define MTDPART_SIZ_FULL    (0)

int add_mtd_partitions(struct mtd_info *, struct mtd_partition *, int);//int表示几个分区, sizeof(s3c2410_partitions) / sizeof(struct mtd_partition)
int del_mtd_partitions(struct mtd_info *);

/*defined in include/linux/mtd/map.h*/
/* The map stuff is very simple. You fill in your struct map_info with
   a handful of routines for accessing the device, making sure they handle
   paging etc. correctly if your device needs it. Then you pass it off
   to a chip driver which deals with a mapped device - generally either
   do_cfi_probe() or do_ram_probe(), either of which will return a
   struct mtd_info if they liked what they saw. At which point, you
   fill in the mtd->module with your own module address, and register
   it.
   
   The mtd->priv field will point to the struct map_info, and any further
   private data required by the chip driver is linked from the
   mtd->priv->fldrv_priv field. This allows the map driver to get at
   the destructor function map->fldrv_destroy() when it's tired
   of living.
*/
struct map_info {
    char *name;
    unsigned long size;
    int buswidth; /* in octets */
    __u8 (*read8)(struct map_info *, unsigned long);
    __u16 (*read16)(struct map_info *, unsigned long);
    __u32 (*read32)(struct map_info *, unsigned long);  
    __u64 (*read64)(struct map_info *, unsigned long);  
    /* If it returned a 'long' I'd call it readl.
     * It doesn't.
     * I won't.
     * dwmw2 */
   
    void (*copy_from)(struct map_info *, void *, unsigned long, ssize_t);
    void (*write8)(struct map_info *, __u8, unsigned long);
    void (*write16)(struct map_info *, __u16, unsigned long);
    void (*write32)(struct map_info *, __u32, unsigned long);
    void (*write64)(struct map_info *, __u64, unsigned long);
    void (*copy_to)(struct map_info *, unsigned long, const void *, ssize_t);

    void (*set_vpp)(struct map_info *, int);
    /* We put these two here rather than a single void *map_priv,
       because we want mappers to be able to have quickly-accessible
       cache for the 'currently-mapped page' without the _extra_
       redirection that would be necessary. If you need more than
       two longs, turn the second into a pointer. dwmw2 */
    unsigned long map_priv_1;
    unsigned long map_priv_2;
    void *fldrv_priv;
    struct mtd_chip_driver *fldrv;
};


struct mtd_chip_driver {
    struct mtd_info *(*probe)(struct map_info *map);
    void (*destroy)(struct mtd_info *);
    struct module *module;
    char *name;
    struct list_head list;
};
struct mtd_info *do_map_probe(const char *name, struct map_info *map);

/*defined in include/linux/mtd/mtd.h*/
struct mtd_info {
    u_char type;
    u_int32_t flags;
    u_int32_t size; // Total size of the MTD

    /* "Major" erase size for the device. Na飗e users may take this
     * to be the only erase size available, or may use the more detailed
     * information below if they desire
     */
    u_int32_t erasesize;

    u_int32_t oobblock;  // Size of OOB blocks (e.g. 512)
    u_int32_t oobsize;   // Amount of OOB data per block (e.g. 16)
    u_int32_t ecctype;
    u_int32_t eccsize;

    // Kernel-only stuff starts here.
    char *name;
    int index;

    /* Data for variable erase regions. If numeraseregions is zero,
     * it means that the whole device has erasesize as given above.
     */
    int numeraseregions;
    struct mtd_erase_region_info *eraseregions;

    /* This really shouldn't be here. It can go away in 2.5 */
    u_int32_t bank_size;

    struct module *module;
    int (*erase) (struct mtd_info *mtd, struct erase_info *instr);

    /* This stuff for eXecute-In-Place */
    int (*point) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf);

    /* We probably shouldn't allow XIP if the unpoint isn't a NULL */
    void (*unpoint) (struct mtd_info *mtd, u_char * addr);


    int (*read) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
    int (*write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);

    int (*read_ecc) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf, u_char *eccbuf);
    int (*write_ecc) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf, u_char *eccbuf);

    int (*read_oob) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
    int (*write_oob) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);

    /*
     * Methods to access the protection register area, present in some
     * flash devices. The user data is one time programmable but the
     * factory data is read only.
     */
    int (*read_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);

    int (*read_fact_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);

    /* This function is not yet implemented */
    int (*write_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);

    /* iovec-based read/write methods. We need these especially for NAND flash,
       with its limited number of write cycles per erase.
       NB: The 'count' parameter is the number of _vectors_, each of
       which contains an (ofs, len) tuple.
    */
    int (*readv) (struct mtd_info *mtd, struct iovec *vecs, unsigned long count, loff_t from, size_t *retlen);
    int (*writev) (struct mtd_info *mtd, const struct iovec *vecs, unsigned long count, loff_t to, size_t *retlen);

    /* Sync */
    void (*sync) (struct mtd_info *mtd);

    /* Chip-supported device locking */
    int (*lock) (struct mtd_info *mtd, loff_t ofs, size_t len);
    int (*unlock) (struct mtd_info *mtd, loff_t ofs, size_t len);

    /* Power Management functions */
    int (*suspend) (struct mtd_info *mtd);
    void (*resume) (struct mtd_info *mtd);

    void *priv;
};

/*
* Normal mappings of chips on Samsung s3c2410 in physical memory
*/

#include
#include
#include
#include
#include
#include
#include
#include

#define WINDOW_ADDR 0x01000000 //禄霉
#define WINDOW_SIZE 0x01600000   //flash麓贸16M
#define BUSWIDTH 2

/*defined in include/linux/mtd/mtd.h*/
static struct mtd_info *mymtd;

__u8 s3c2410_read8(struct map_info *map, unsigned long ofs)
{
        return readb(map->map_priv_1 + ofs);
}

__u16 s3c2410_read16(struct map_info *map, unsigned long ofs)
{
        return readw(map->map_priv_1 + ofs);
               }

__u32 s3c2410_read32(struct map_info *map, unsigned long ofs)
{
        return readl(map->map_priv_1 + ofs);
}

void s3c2410_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
{
        memcpy(to, (void *)(map->map_priv_1 + from), len);
}

void s3c2410_write8(struct map_info *map, __u8 d, unsigned long adr)
{
        writeb(d, map->map_priv_1 + adr);
}

void s3c2410_write16(struct map_info *map, __u16 d, unsigned long adr)
{
        writew(d, map->map_priv_1 + adr);
}
void s3c2410_write32(struct map_info *map, __u32 d, unsigned long adr)
{
        writel(d, map->map_priv_1 + adr);
}

void s3c2410_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
{
        memcpy((void *)(map->map_priv_1 + to), from, len);
}
/*defined in include/linux/mtd/map.h*/
struct map_info s3c2410_map = {
        name: "s3c2410 flash device",
        size: WINDOW_SIZE,
        buswidth: BUSWIDTH,
        read8: s3c2410_read8,
        read16: s3c2410_read16,
        read32: s3c2410_read32,
        copy_from: s3c2410_copy_from,
        write8: s3c2410_write8,
        write16: s3c2410_write16,
             write32: s3c2410_write32,
        copy_to: s3c2410_copy_to,
    /* We put these two here rather than a single void *map_priv,
       because we want mappers to be able to have quickly-accessible
       cache for the 'currently-mapped page' without the _extra_
       redirection that would be necessary. If you need more than
       two longs, turn the second into a pointer. dwmw2 */
        map_priv_1:     WINDOW_ADDR,
        map_priv_2:     -1,
};
//脪脧脢路脰酶脠拢卢碌卤然要赂霉脳录潞碌脛猫确露篓脕
static struct mtd_partition s3c2410_partitions[] = {
    {
            name: "reserved for bootloader",
            size: 0x040000,
            offset: 0x0,
                        mask_flags: MTD_WRITEABLE,
    },
    {
            name: "reserved for kernel",
            size: 0x0100000,
            offset: 0x040000,
                        mask_flags: MTD_WRITEABLE,
    },
    {
            name: "reserved for ramdisk",
        size: 0x400000,
            offset: 0x140000,
                        mask_flags: MTD_WRITEABLE,

    },
    {
                name: "jffs2(8M)",
                size: 0x700000,
                offset: 0x800000,
        },
    {
        name: "cramfs(2.75M)",
        size:0x2c0000,
        offset:0x540000,
    }

};

int __init init_s3c2410(void)
{
    printk(KERN_NOTICE "s3c2410 flash device: %x at %x\n", WINDOW_SIZE, WINDOW_ADDR);
/*get line addr from physical addr*/
        s3c2410_map.map_priv_1 = (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE);
        //printk("0\n");
        if (!s3c2410_map.map_priv_1) {
                printk("Failed to ioremap/n");
                return -EIO;
                         }
        //printk("1\n");
        mymtd = do_map_probe("jedec_probe", &s3c2410_map);
        if (!mymtd)
        mymtd = do_map_probe("cfi_probe", &s3c2410_map);
        //printk("2\n");
        if (mymtd) {
                mymtd->module = THIS_MODULE;
                mymtd->erasesize = 0x20000; //INTEL E28F128J3A-150:128kb
/*here,we need not consider mtd_parts_nb,not call
parse_cmdline_partitions,because it's 5 indeed.we can obtain the size of partitions*/
                return add_mtd_partitions(mymtd, s3c2410_partitions, sizeof(s3c2410_partitions) / sizeof(struct mtd_partition));
        }
        //printk("3\n");
        iounmap((void *)s3c2410_map.map_priv_1);
        return -ENXIO;
}

static void __exit cleanup_s3c2410(void)
{
        if (mymtd) {
                del_mtd_partitions(mymtd);
                  map_destroy(mymtd);
        }
        if (s3c2410_map.map_priv_1) {
                iounmap((void *)s3c2410_map.map_priv_1);
                s3c2410_map.map_priv_1 = 0;
        }
}

module_init(init_s3c2410);
module_exit(cleanup_s3c2410);

JEDEC Flash Interface.
* This is an older type of interface for self programming flash. It is commonly use in older AMD chips and is obsolete compared with CFI.It is called  JEDEC because the JEDEC association distributes the ID codes for the chips.This code does not support anything wider than 8 bit flash chips

Common Flash Interface:
Common code to handle map devices which are simple ROM:




本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/15906/showart_88176.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP