NORFlash协议层

1、CFI mode:
①、注册 cfi_chipdrv :

static int __init cfi_probe_init(void)
{
    register_mtd_chip_driver(&cfi_chipdrv);
    return 0;
}
/* linux-3.4.2\drivers\mtd\chips\cfi_probe.c */

在cfi_probe_init函数中调用register_mtd_chip_driver函数,将cfi_chipdrv 添加到chip_drvs_list中去:

void register_mtd_chip_driver(struct mtd_chip_driver *drv)
{
    spin_lock(&chip_drvs_lock);
    list_add(&drv->list, &chip_drvs_list);
    spin_unlock(&chip_drvs_lock);
}
/* linux-3.4.2\drivers\mtd\chips\chipreg.c */

其中,cfi_chipdrv 结构体变量定义如下:

static struct mtd_chip_driver cfi_chipdrv = {
    .probe      = cfi_probe,
    .name       = "cfi_probe",
    .module     = THIS_MODULE
};
/* linux-3.4.2\drivers\mtd\chips\cfi_probe.c */

②、do_map_probe执行过程:
在do_map_probe函数中调用get_mtd_chip_driver函数 :

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

    ...

}
/* linux-3.4.2\drivers\mtd\chips\chipreg.c */

依次列举chip_drvs_list中的mtd_chip_driver 项,将每一项的成员name和传入参数name做比较,返回name相同的mtd_chip_driver 项,返回值ret = &cfi_chipdrv给do_map_probe函数中的drv:

static struct mtd_chip_driver *get_mtd_chip_driver (const char *name)
{
    struct list_head *pos;
    struct mtd_chip_driver *ret = NULL, *this;

    spin_lock(&chip_drvs_lock);

    list_for_each(pos, &chip_drvs_list) {
        this = list_entry(pos, typeof(*this), list);

        if (!strcmp(this->name, name)) {
            ret = this;
            break;
        }
    }
    if (ret && !try_module_get(ret->module))
        ret = NULL;

    spin_unlock(&chip_drvs_lock);

    return ret; //ret = &cfi_chipdrv
}
/* linux-3.4.2\drivers\mtd\chips\chipreg.c */

再由mtd_chip_driver返回do_map_probe执行drv->probe(map):

struct mtd_info *do_map_probe(const char *name, struct map_info *map)
{
    struct mtd_chip_driver *drv;
    struct mtd_info *ret;

    ...

    ret = drv->probe(map); //drv = &cfi_chipdrv

    ...

    return ret;
}
/* linux-3.4.2\drivers\mtd\chips\chipreg.c */

由于drv = &cfi_chipdrv,执行执行drv->probe即相当于执行cfi_chipdrv.probe = cfi_probe:

struct mtd_info *cfi_probe(struct map_info *map)
{
    /*
     * Just use the generic probe stuff to call our CFI-specific
     * chip_probe routine in all the possible permutations, etc.
     */
    return mtd_do_chip_probe(map, &cfi_chip_probe);
}
/* linux-3.4.2\drivers\mtd\chips\cfi_probe.c */

其中,cfi_chip_probe如下定义:

static struct chip_probe cfi_chip_probe = {
    .name       = "CFI",
    .probe_chip = cfi_probe_chip
};
/* linux-3.4.2\drivers\mtd\chips\cfi_probe.c */

cfi_probe ->mtd_do_chip_probe:

struct mtd_info *mtd_do_chip_probe(struct map_info *map, struct chip_probe *cp)
{
    struct mtd_info *mtd = NULL;
    struct cfi_private *cfi;

    /* First probe the map to see if we have CFI stuff there. */
    cfi = genprobe_ident_chips(map, cp); //cp = &cfi_chip_probe 

    ...

}
/* linux-3.4.2\drivers\mtd\chips\gen_probe.c */

mtd_do_chip_probe->genprobe_ident_chips:

static struct cfi_private *genprobe_ident_chips(struct map_info *map, struct chip_probe *cp)
{
    struct cfi_private cfi;
    struct cfi_private *retcfi;
    unsigned long *chip_map;
    int i, j, mapsize;
    int max_chips;

    memset(&cfi, 0, sizeof(cfi));

    /* Call the probetype-specific code with all permutations of
       interleave and device type, etc. */
    if (!genprobe_new_chip(map, cp, &cfi)) {
        /* The probe didn't like it */
        pr_debug("%s: Found no %s device at location zero\n",
             cp->name, map->name);
        return NULL;
    }

    ...

}
/* linux-3.4.2\drivers\mtd\chips\gen_probe.c */

genprobe_ident_chips->genprobe_new_chip执行cp->probe_chip:

static int genprobe_new_chip(struct map_info *map, struct chip_probe *cp,
                 struct cfi_private *cfi)
{
    int min_chips = (map_bankwidth(map)/4?:1); /* At most 4-bytes wide. */
    int max_chips = map_bankwidth(map); /* And minimum 1 */
    int nr_chips, type;

    for (nr_chips = max_chips; nr_chips >= min_chips; nr_chips >>= 1) {

        ...

        for (; type <= CFI_DEVICETYPE_X32; type<<=1) {

            ...

            if (cp->probe_chip(map, 0, NULL, cfi))
                return 1;
        }
    }
    return 0;
}
/* linux-3.4.2\drivers\mtd\chips\gen_probe.c */

由于cp = &cfi_chip_probe 所以执行执行cp->probe_chip相当于执行cfi_chip_probe.probe_chip = cfi_probe_chip。
2、JEDEC mode:
①、注册jedec_chipdrv :

static int __init jedec_probe_init(void)
{
    register_mtd_chip_driver(&jedec_chipdrv);
    return 0;
}

在jedec_probe_init函数中调用register_mtd_chip_driver函数,将jedec_chipdrv 添加到chip_drvs_list中去:

void register_mtd_chip_driver(struct mtd_chip_driver *drv)
{
    spin_lock(&chip_drvs_lock);
    list_add(&drv->list, &chip_drvs_list);
    spin_unlock(&chip_drvs_lock);
}

其中,jedec_chipdrv 定义如下:

static struct mtd_chip_driver jedec_chipdrv = {
    .probe  = jedec_probe,
    .name   = "jedec_probe",
    .module = THIS_MODULE
};

②、do_map_probe执行过程:
在do_map_probe函数中调用get_mtd_chip_driver函数 :

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

    ...

}
/* linux-3.4.2\drivers\mtd\chips\chipreg.c */

依次列举chip_drvs_list中的mtd_chip_driver 项,将每一项的成员name和传入参数name做比较,返回name相同的mtd_chip_driver 项,返回值ret = &jedec_chipdrv 给do_map_probe函数中的drv:

static struct mtd_chip_driver *get_mtd_chip_driver (const char *name)
{
    struct list_head *pos;
    struct mtd_chip_driver *ret = NULL, *this;

    spin_lock(&chip_drvs_lock);

    list_for_each(pos, &chip_drvs_list) {
        this = list_entry(pos, typeof(*this), list);

        if (!strcmp(this->name, name)) {
            ret = this;
            break;
        }
    }
    if (ret && !try_module_get(ret->module))
        ret = NULL;

    spin_unlock(&chip_drvs_lock);

    return ret; //ret = &jedec_chipdrv 
}
/* linux-3.4.2\drivers\mtd\chips\chipreg.c */

再由mtd_chip_driver返回do_map_probe执行drv->probe(map):

struct mtd_info *do_map_probe(const char *name, struct map_info *map)
{
    struct mtd_chip_driver *drv;
    struct mtd_info *ret;

    ...

    ret = drv->probe(map); //drv = &jedec_chipdrv 

    ...

    return ret;
}
/* linux-3.4.2\drivers\mtd\chips\chipreg.c */

由于drv = &jedec_chipdrv ,执行执行drv->probe即相当于执行jedec_chipdrv .probe = jedec_probe:

static struct mtd_info *jedec_probe(struct map_info *map)
{
    /*
     * Just use the generic probe stuff to call our CFI-specific
     * chip_probe routine in all the possible permutations, etc.
     */
    return mtd_do_chip_probe(map, &jedec_chip_probe);
}
/* linux-3.4.2\drivers\mtd\chips\jedec_probe.c */

其中,jedec_chip_probe 定义如下:

static struct chip_probe jedec_chip_probe = {
    .name = "JEDEC",
    .probe_chip = jedec_probe_chip
};
/* linux-3.4.2\drivers\mtd\chips\jedec_probe.c */

jedec_probe->mtd_do_chip_probe:

struct mtd_info *mtd_do_chip_probe(struct map_info *map, struct chip_probe *cp)
{
    struct mtd_info *mtd = NULL;
    struct cfi_private *cfi;

    /* First probe the map to see if we have CFI stuff there. */
    cfi = genprobe_ident_chips(map, cp); //cp = &cfi_chip_probe 

    ...

}
/* linux-3.4.2\drivers\mtd\chips\gen_probe.c */

mtd_do_chip_probe->genprobe_ident_chips:

static struct cfi_private *genprobe_ident_chips(struct map_info *map, struct chip_probe *cp)
{
    struct cfi_private cfi;
    struct cfi_private *retcfi;
    unsigned long *chip_map;
    int i, j, mapsize;
    int max_chips;

    memset(&cfi, 0, sizeof(cfi));

    /* Call the probetype-specific code with all permutations of
       interleave and device type, etc. */
    if (!genprobe_new_chip(map, cp, &cfi)) {
        /* The probe didn't like it */
        pr_debug("%s: Found no %s device at location zero\n",
             cp->name, map->name);
        return NULL;
    }

    ...

}
/* linux-3.4.2\drivers\mtd\chips\gen_probe.c */

genprobe_ident_chips->genprobe_new_chip执行cp->probe_chip:

static int genprobe_new_chip(struct map_info *map, struct chip_probe *cp,
                 struct cfi_private *cfi)
{
    int min_chips = (map_bankwidth(map)/4?:1); /* At most 4-bytes wide. */
    int max_chips = map_bankwidth(map); /* And minimum 1 */
    int nr_chips, type;

    for (nr_chips = max_chips; nr_chips >= min_chips; nr_chips >>= 1) {

        ...

        for (; type <= CFI_DEVICETYPE_X32; type<<=1) {

            ...

            if (cp->probe_chip(map, 0, NULL, cfi))
                return 1;
        }
    }
    return 0;
}
/* linux-3.4.2\drivers\mtd\chips\gen_probe.c */

由于cp = &jedec_chip_probe,所以执行执行cp->probe_chip相当于执行jedec_chip_probe.probe_chip =jedec_probe_chip 。

你可能感兴趣的:(4,嵌入式驱动,--->块设备驱动)