本文主要是介绍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 ofinterleave 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 ofinterleave 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 。
这篇关于NORFlash协议层的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!