第19章Flash设备驱动之Nor Flash驱动

19.2 Nor Flash驱动

    在 Linux 系统中,实现了针对 CFI(公共 Flash 接口)、JEDEC(电子元件工业联合会)等接口的通用 NOR 驱动,这一层的驱动直接面向 mtd_info 的成员函数,这使得 NOR 的芯片级驱动变得十分简单,只需要定义具体的内存映射情况结构体 map_info 并使用指定接口类型调用 do_map_ probe()


图19.3 MTD、通用 NOR Flash驱动与 map_info

    NOR Flash 驱动的核心是定义 map_info 结构体,指定NOR Flash 的基址、位宽、大小等信息以及 Flash 的读写函数,该结构体对于 NOR Flash 驱动非常关键,甚至NOR Flash 驱动的代码本质上可以被认作是根据 map_info 探测芯片的过程,其定义如代码清单 19.7 所示。

代码清单 19.7 map_info 结构体

include/linux/mtd/map.h

struct map_info {
        char *name;
        unsigned long size;
        resource_size_t phys;
#define NO_XIP (-1UL)

        void __iomem *virt;/* 虚拟地址 */
        void *cached;

        int bankwidth; /* 总线宽度 */

#ifdef CONFIG_MTD_COMPLEX_MAPPINGS
        map_word (*read)(struct map_info *, unsigned long);
        void (*copy_from)(struct map_info *, void *, unsigned long, ssize_t);

        void (*write)(struct map_info *, const map_word, unsigned long);
        void (*copy_to)(struct map_info *, unsigned long, const void *, ssize_t);
#endif
        /* 缓存的虚拟地址 */
        void (*inval_cache)(struct map_info *, unsigned long, ssize_t);

        void (*set_vpp)(struct map_info *, int);

        unsigned long map_priv_1;
        unsigned long map_priv_2;
        void *fldrv_priv;
        struct mtd_chip_driver *fldrv;

};

NOR Flash 驱动在 Linux 中的实现简单,如图 19.4 所示,主要的工作如下。


扫描二维码关注公众号,回复: 1689920 查看本文章

图19.4 NOR Flash 驱动

(1)定义 map_info 的实例,初始化其中的成员,根据目标板的情况为 name、size、bankwidth和 phys 赋值。

(2)如果 Flash 要分区,则定义 mtd_partition 数组,将实际电路板中 Flash 分区信息记录于其中。

(3)以map_info 和探测的接口类型(如"cfi_probe"、"jedec_probe"等)为参数调用do_map_ probe(),探测 Flash 得到 mtd_info。

do_map_probe()的函数原型为:

struct mtd_info *do_map_probe(const char *name, struct map_info *map);

第一个参数为探测的接口类型,常见的调用方法如下。

do_map_probe("cfi_probe",&xxx_map_info);
do_map_probe("jedec_probe",&xxx_map_info);
do_map_probe("map_rom",&xxx_ma _info);

do_map_probe()会根据传入的参数 name  通过 get_mtd_chip_driver()得到具体的 MTD 驱动,调用与接口对应的 probe()函数探测设备,如代码清单 19.8 所示。

代码清单 19.8 do_map_probe()函数

struct mtd _ info *do _ map _ probe(const char *name, struct map _ info *map)
 {
         struct mtd _ chip _ driver *drv;
         struct mtd _ info *ret;

         drv = get_mtd_chip_driver(name);/* 通过名称获得驱动 */

         if (!drv && !request _ module("%s", name))
             drv = get_mtd_chip_driver(name);

        if (!drv)
             return NULL;

        ret = drv->probe(map);/* 调用驱动的探测函数 */

         module _ put(drv!module);
         if (ret)
             return ret;

         return NULL;
 }

分析:

        利用 map_info 中的配置,do_map_probe()可以自动识别支持 CFI 或 JEDEC 接口的 Flash 芯片,MTD 以后会自动采用适当的命令参数对 Flash 进行读写或擦除。

(4)在模块初始化时以 mtd_info 为参数调用 add_mtd_device()或以 mtd_info、mtd_partition 数组及分区数为参数调用add_mtd_partitions()注册设备或分区。当然,在这之前可以调用parse_mtd_partitions()查看Flash 上是否已有分区信息,并将查看出的分区信息通过add_mtd_partitions()注册。

(5)在模块卸载时删除设备或分区。

猜你喜欢

转载自blog.csdn.net/xiezhi123456/article/details/80761530
今日推荐