⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sa1100-flash.c

📁 ARM S3C2410 linux2.4 内核源码
💻 C
📖 第 1 页 / 共 2 页
字号:
		.name		= "STORK root jffs2",		.offset		= 0x00180000,		.size		= MTDPART_SIZ_FULL,#else		.name		= "STORK initrd",		.size		= 0x00100000,		.offset		= 0x00180000,	}, {		.name		= "STORK root cramfs",		.size		= 0x00300000,		.offset		= 0x00280000,	}, {		.name		= "STORK usr cramfs",		.size		= 0x00800000,		.offset		= 0x00580000,	}, {		.name		= "STORK usr local",		.offset		= 0x00d80000,		.size		= MTDPART_SIZ_FULL,#endif	}};#endif#ifdef CONFIG_SA1100_TRIZEPSstatic struct mtd_partition trizeps_partitions[] = {	{		.name		= "Bootloader",		.size		= 0x00100000,		.offset		= 0,	}, {		.name		= "Kernel",		.size		= 0x00100000,		.offset		= MTDPART_OFS_APPEND,	}, {		.name		= "root",		.size		= MTDPART_SIZ_FULL,		.offset		= MTDPART_OFS_APPEND,	}};#endif#ifdef CONFIG_SA1100_YOPYstatic struct mtd_partition yopy_partitions[] = {	{		.name		= "boot firmware",		.size		= 0x00040000,		.offset		= 0x00000000,		.mask_flags	= MTD_WRITEABLE,  /* force read-only */	}, {		.name		= "kernel",		.size		= 0x00080000,		.offset		= 0x00080000,	}, {		.name		= "initrd",		.size		= 0x00300000,		.offset		= 0x00100000,	}, {		.name		= "root",		.size		= 0x01000000,		.offset		= 0x00400000,	}};#endifstatic int __init sa1100_static_partitions(struct mtd_partition **parts){	int nb_parts = 0;#ifdef CONFIG_SA1100_ADSBITSY	if (machine_is_adsbitsy()) {		*parts       = adsbitsy_partitions;		nb_parts     = ARRAY_SIZE(adsbitsy_partitions);	}#endif#ifdef CONFIG_SA1100_ASSABET	if (machine_is_assabet()) {		*parts       = assabet_partitions;		nb_parts     = ARRAY_SIZE(assabet_partitions);	}#endif#ifdef CONFIG_SA1100_BADGE4	if (machine_is_badge4()) {		*parts       = badge4_partitions;		nb_parts     = ARRAY_SIZE(badge4_partitions);	}#endif#ifdef CONFIG_SA1100_CERF	if (machine_is_cerf()) {		*parts       = cerf_partitions;		nb_parts     = ARRAY_SIZE(cerf_partitions);	}#endif#ifdef CONFIG_SA1100_CONSUS	if (machine_is_consus()) {		*parts       = consus_partitions;		nb_parts     = ARRAY_SIZE(consus_partitions);	}#endif#ifdef CONFIG_SA1100_FLEXANET	if (machine_is_flexanet()) {		*parts       = flexanet_partitions;		nb_parts     = ARRAY_SIZE(flexanet_partitions);	}#endif#ifdef CONFIG_SA1100_FREEBIRD	if (machine_is_freebird()) {		*parts       = freebird_partitions;		nb_parts     = ARRAY_SIZE(freebird_partitions);	}#endif#ifdef CONFIG_SA1100_FRODO	if (machine_is_frodo()) {		*parts       = frodo_partitions;		nb_parts     = ARRAY_SIZE(frodo_partitions);	}#endif	#ifdef CONFIG_SA1100_GRAPHICSCLIENT	if (machine_is_graphicsclient()) {		*parts       = graphicsclient_partitions;		nb_parts     = ARRAY_SIZE(graphicsclient_partitions);	}#endif#ifdef CONFIG_SA1100_GRAPHICSMASTER	if (machine_is_graphicsmaster()) {		*parts       = graphicsmaster_partitions;		nb_parts     = ARRAY_SIZE(graphicsmaster_partitions);	}#endif#ifdef CONFIG_SA1100_H3XXX	if (machine_is_h3xxx()) {		*parts       = h3xxx_partitions;		nb_parts     = ARRAY_SIZE(h3xxx_partitions);	}#endif#ifdef CONFIG_SA1100_HACKKIT	if (machine_is_hackkit()) {		*parts = hackkit_partitions;		nb_parts = ARRAY_SIZE(hackkit_partitions);	}#endif#ifdef CONFIG_SA1100_HUW_WEBPANEL	if (machine_is_huw_webpanel()) {		*parts       = huw_webpanel_partitions;		nb_parts     = ARRAY_SIZE(huw_webpanel_partitions);	}#endif#ifdef CONFIG_SA1100_JORNADA720	if (machine_is_jornada720()) {		*parts       = jornada720_partitions;		nb_parts     = ARRAY_SIZE(jornada720_partitions);	}#endif#ifdef CONFIG_SA1100_PANGOLIN	if (machine_is_pangolin()) {		*parts       = pangolin_partitions;		nb_parts     = ARRAY_SIZE(pangolin_partitions);	}#endif#ifdef CONFIG_SA1100_PT_SYSTEM3	if (machine_is_pt_system3()) {		*parts       = system3_partitions;		nb_parts     = ARRAY_SIZE(system3_partitions);	}#endif#ifdef CONFIG_SA1100_SHANNON	if (machine_is_shannon()) {		*parts       = shannon_partitions;		nb_parts     = ARRAY_SIZE(shannon_partitions);	}#endif#ifdef CONFIG_SA1100_SHERMAN	if (machine_is_sherman()) {		*parts       = sherman_partitions;		nb_parts     = ARRAY_SIZE(sherman_partitions);	}#endif#ifdef CONFIG_SA1100_SIMPAD	if (machine_is_simpad()) {		*parts       = simpad_partitions;		nb_parts     = ARRAY_SIZE(simpad_partitions);	}#endif#ifdef CONFIG_SA1100_STORK	if (machine_is_stork()) {		*parts       = stork_partitions;		nb_parts     = ARRAY_SIZE(stork_partitions);	}#endif#ifdef CONFIG_SA1100_TRIZEPS	if (machine_is_trizeps()) {		*parts       = trizeps_partitions;		nb_parts     = ARRAY_SIZE(trizeps_partitions);	}#endif#ifdef CONFIG_SA1100_YOPY	if (machine_is_yopy()) {		*parts       = yopy_partitions;		nb_parts     = ARRAY_SIZE(yopy_partitions);	}#endif	return nb_parts;}#endifstruct sa_info {	unsigned long base;	unsigned long size;	int width;	void *vbase;        void (*set_vpp)(struct map_info *, int);	struct map_info *map;	struct mtd_info *mtd;	struct resource *res;};#define NR_SUBMTD 4static struct sa_info info[NR_SUBMTD];static int __init sa1100_setup_mtd(struct sa_info *sa, int nr, struct mtd_info **rmtd){	struct mtd_info *subdev[nr];	struct map_info *maps;	int i, found = 0, ret = 0;	/*	 * Allocate the map_info structs in one go.	 */	maps = kmalloc(sizeof(struct map_info) * nr, GFP_KERNEL);	if (!maps)		return -ENOMEM;	memset(maps, 0, sizeof(struct map_info) * nr);	/*	 * Claim and then map the memory regions.	 */	for (i = 0; i < nr; i++) {		if (sa[i].base == (unsigned long)-1)			break;		sa[i].res = request_mem_region(sa[i].base, sa[i].size, "sa1100 flash");		if (!sa[i].res) {			ret = -EBUSY;			break;		}		sa[i].map = maps + i;		sa[i].vbase = ioremap(sa[i].base, sa[i].size);		if (!sa[i].vbase) {			ret = -ENOMEM;			break;		}		sa[i].map->virt = (unsigned long)sa[i].vbase;		sa[i].map->phys = sa[i].base;		sa[i].map->set_vpp = sa[i].set_vpp;		sa[i].map->buswidth = sa[i].width;		sa[i].map->size = sa[i].size;		simple_map_init(sa[i].map);		/*		 * Now let's probe for the actual flash.  Do it here since		 * specific machine settings might have been set above.		 */		sa[i].mtd = do_map_probe("cfi_probe", sa[i].map);		if (sa[i].mtd == NULL) {			ret = -ENXIO;			break;		}		sa[i].mtd->owner = THIS_MODULE;		subdev[i] = sa[i].mtd;		printk(KERN_INFO "SA1100 flash: CFI device at 0x%08lx, %dMiB, "			"%d-bit\n", sa[i].base, sa[i].mtd->size >> 20,			sa[i].width * 8);		found += 1;	}	/*	 * ENXIO is special.  It means we didn't find a chip when	 * we probed.  We need to tear down the mapping, free the	 * resource and mark it as such.	 */	if (ret == -ENXIO) {		iounmap(sa[i].vbase);		sa[i].vbase = NULL;		release_resource(sa[i].res);		sa[i].res = NULL;	}	/*	 * If we found one device, don't bother with concat support.	 * If we found multiple devices, use concat if we have it	 * available, otherwise fail.	 */	if (ret == 0 || ret == -ENXIO) {		if (found == 1) {			*rmtd = subdev[0];			ret = 0;		} else if (found > 1) {			/*			 * We detected multiple devices.  Concatenate			 * them together.			 */#ifdef CONFIG_MTD_CONCAT			*rmtd = mtd_concat_create(subdev, found,						  "sa1100 flash");			if (*rmtd == NULL)				ret = -ENXIO;#else			printk(KERN_ERR "SA1100 flash: multiple devices "			       "found but MTD concat support disabled.\n");			ret = -ENXIO;#endif		}	}	/*	 * If we failed, clean up.	 */	if (ret) {		do {			if (sa[i].mtd)				map_destroy(sa[i].mtd);			if (sa[i].vbase)				iounmap(sa[i].vbase);			if (sa[i].res)				release_resource(sa[i].res);		} while (i--);		kfree(maps);	}	return ret;}static void __exit sa1100_destroy_mtd(struct sa_info *sa, struct mtd_info *mtd){	int i;	del_mtd_partitions(mtd);#ifdef CONFIG_MTD_CONCAT	if (mtd != sa[0].mtd)		mtd_concat_destroy(mtd);#endif	for (i = NR_SUBMTD; i >= 0; i--) {		if (sa[i].mtd)			map_destroy(sa[i].mtd);		if (sa[i].vbase)			iounmap(sa[i].vbase);		if (sa[i].res)			release_resource(sa[i].res);	}	kfree(sa[0].map);}/* * A Thought: can we automatically detect the flash? *  - Check to see if the region is busy (yes -> failure) *  - Is the MSC setup for flash (no -> failure) *  - Probe for flash */static struct map_info sa1100_probe_map __initdata = {	.name		= "SA1100-flash",};static void __init sa1100_probe_one_cs(unsigned int msc, unsigned long phys){	struct mtd_info *mtd;	printk(KERN_INFO "* Probing 0x%08lx: MSC = 0x%04x %d bit ",		phys, msc & 0xffff, msc & MSC_RBW ? 16 : 32);	if (check_mem_region(phys, 0x08000000)) {		printk("busy\n");		return;	}	if ((msc & 3) == 1) {		printk("wrong type\n");		return;	}	sa1100_probe_map.buswidth = msc & MSC_RBW ? 2 : 4;	sa1100_probe_map.size = SZ_1M;	sa1100_probe_map.phys = phys;	sa1100_probe_map.virt = (unsigned long)ioremap(phys, SZ_1M);	if (sa1100_probe_map.virt == 0)		goto fail;	simple_map_init(&sa1100_probe_map);	/* Shame cfi_probe blurts out kernel messages... */	mtd = do_map_probe("cfi_probe", &sa1100_probe_map);	if (mtd)		map_destroy(mtd);	iounmap((void *)sa1100_probe_map.virt);	if (!mtd)		goto fail;	printk("pass\n");	return; fail:	printk("failed\n");}static void __init sa1100_probe_flash(void){	printk(KERN_INFO "-- SA11xx Flash probe.  Please report results.\n");	sa1100_probe_one_cs(MSC0, SA1100_CS0_PHYS);	sa1100_probe_one_cs(MSC0 >> 16, SA1100_CS1_PHYS);	sa1100_probe_one_cs(MSC1, SA1100_CS2_PHYS);	sa1100_probe_one_cs(MSC1 >> 16, SA1100_CS3_PHYS);	sa1100_probe_one_cs(MSC2, SA1100_CS4_PHYS);	sa1100_probe_one_cs(MSC2 >> 16, SA1100_CS5_PHYS);	printk(KERN_INFO "-- SA11xx Flash probe complete.\n");}static int __init sa1100_locate_flash(void){	int i, nr = -ENODEV;	sa1100_probe_flash();	if (machine_is_adsbitsy()) {		info[0].base = SA1100_CS1_PHYS;		info[0].size = SZ_32M;		nr = 1;	}	if (machine_is_assabet()) {		info[0].base = SA1100_CS0_PHYS;		info[0].size = SZ_32M;		info[1].base = SA1100_CS1_PHYS; /* neponset */		info[1].size = SZ_32M;		nr = 2;	}	if (machine_is_badge4()) {		info[0].base = SA1100_CS0_PHYS;		info[0].size = SZ_64M;		nr = 1;	}	if (machine_is_cerf()) {		info[0].base = SA1100_CS0_PHYS;		info[0].size = SZ_32M;		nr = 1;	}	if (machine_is_consus()) {		info[0].base = SA1100_CS0_PHYS;		info[0].size = SZ_32M;		nr = 1;	}	if (machine_is_flexanet()) {		info[0].base = SA1100_CS0_PHYS;		info[0].size = SZ_32M;		nr = 1;	}	if (machine_is_freebird()) {		info[0].base = SA1100_CS0_PHYS;		info[0].size = SZ_32M;		nr = 1;	}	if (machine_is_frodo()) {		info[0].base = SA1100_CS0_PHYS;		info[0].size = SZ_32M;		nr = 1;	}	if (machine_is_graphicsclient()) {		info[0].base = SA1100_CS1_PHYS;		info[0].size = SZ_32M;		nr = 1;	}	if (machine_is_graphicsmaster()) {		info[0].base = SA1100_CS1_PHYS;		info[0].size = SZ_16M;		nr = 1;	}	if (machine_is_h3xxx()) {		info[0].set_vpp = h3xxx_set_vpp;		info[0].base = SA1100_CS0_PHYS;		info[0].size = SZ_32M;		nr = 1;	}	if (machine_is_huw_webpanel()) {		info[0].base = SA1100_CS0_PHYS;		info[0].size = SZ_16M;		nr = 1;	}	if (machine_is_itsy()) {		info[0].base = SA1100_CS0_PHYS;		info[0].size = SZ_32M;		nr = 1;	}	if (machine_is_jornada720()) {		info[0].set_vpp = jornada720_set_vpp;		info[0].base = SA1100_CS0_PHYS;		info[0].size = SZ_32M;		nr = 1;	}	if (machine_is_nanoengine()) {		info[0].base = SA1100_CS0_PHYS;		info[1].size = SZ_32M;		nr = 1;	}	if (machine_is_pangolin()) {		info[0].base = SA1100_CS0_PHYS;		info[0].size = SZ_64M;		nr = 1;	}	if (machine_is_pfs168()) {		info[0].base = SA1100_CS0_PHYS;		info[0].size = SZ_32M;		nr = 1;	}	if (machine_is_pleb()) {		info[0].base = SA1100_CS0_PHYS;		info[0].size = SZ_4M;		info[1].base = SA1100_CS1_PHYS;		info[1].size = SZ_4M;		nr = 2;	}	if (machine_is_pt_system3()) {		info[0].base = SA1100_CS0_PHYS;		info[0].size = SZ_16M;		nr = 1;	}	if (machine_is_shannon()) {		info[0].base = SA1100_CS0_PHYS;		info[0].size = SZ_4M;		nr = 1;	}	if (machine_is_sherman()) {		info[0].base = SA1100_CS0_PHYS;		info[0].size = SZ_32M;		nr = 1;	}	if (machine_is_simpad()) {		info[0].base = SA1100_CS0_PHYS;		info[0].size = SZ_16M;		info[1].base = SA1100_CS1_PHYS;		info[1].size = SZ_16M;		nr = 2;	}	if (machine_is_stork()) {		info[0].base = SA1100_CS0_PHYS;		info[0].size = SZ_32M;		nr = 1;	}	if (machine_is_trizeps()) {		info[0].base = SA1100_CS0_PHYS;		info[0].size = SZ_16M;		nr = 1;	}	if (machine_is_victor()) {		info[0].base = SA1100_CS0_PHYS;		info[0].size = SZ_2M;		nr = 1;	}	if (machine_is_yopy()) {		info[0].base = SA1100_CS0_PHYS;		info[0].size = SZ_64M;		info[1].base = SA1100_CS1_PHYS;		info[1].size = SZ_64M;		nr = 2;	}	if (nr < 0)		return nr;	/*	 * Retrieve the buswidth from the MSC registers.	 * We currently only implement CS0 and CS1 here.	 */	for (i = 0; i < nr; i++) {		switch (info[i].base) {		default:			printk(KERN_WARNING "SA1100 flash: unknown base address "				"0x%08lx, assuming CS0\n", info[i].base);		case SA1100_CS0_PHYS:			info[i].width = (MSC0 & MSC_RBW) ? 2 : 4;			break;		case SA1100_CS1_PHYS:			info[i].width = ((MSC0 >> 16) & MSC_RBW) ? 2 : 4;			break;		}	}	return nr;}static struct mtd_partition *parsed_parts;const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL };static void __init sa1100_locate_partitions(struct mtd_info *mtd){	const char *part_type = NULL;	int nr_parts = 0;	do {		/*		 * Partition selection stuff.		 */#ifdef CONFIG_MTD_PARTITIONS		nr_parts = parse_mtd_partitions(mtd, part_probes, &parsed_parts, 0);		if (nr_parts > 0) {			part_type = "dynamic";			break;		}#endif#ifdef CONFIG_MTD_SA1100_STATICMAP		nr_parts = sa1100_static_partitions(&parsed_parts);		if (nr_parts > 0) {			part_type = "static";			break;		}#endif	} while (0);	if (nr_parts == 0) {		printk(KERN_NOTICE "SA1100 flash: no partition info "			"available, registering whole flash\n");		add_mtd_device(mtd);	} else {		printk(KERN_NOTICE "SA1100 flash: using %s partition "			"definition\n", part_type);		add_mtd_partitions(mtd, parsed_parts, nr_parts);	}	/* Always succeeds. */}static void __exit sa1100_destroy_partitions(void){	if (parsed_parts)		kfree(parsed_parts);}static struct mtd_info *mymtd;static int __init sa1100_mtd_init(void){	int ret;	int nr;	nr = sa1100_locate_flash();	if (nr < 0)		return nr;	ret = sa1100_setup_mtd(info, nr, &mymtd);	if (ret == 0)		sa1100_locate_partitions(mymtd);	return ret;}static void __exit sa1100_mtd_cleanup(void){	sa1100_destroy_mtd(info, mymtd);	sa1100_destroy_partitions();}module_init(sa1100_mtd_init);module_exit(sa1100_mtd_cleanup);MODULE_AUTHOR("Nicolas Pitre");MODULE_DESCRIPTION("SA1100 CFI map driver");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -