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

📄 sbc8240.c

📁 linux下的MTD设备驱动源代码,配合jffs2 yaffss2文件系统.
💻 C
字号:
/* * Handle mapping of the flash memory access routines on the SBC8240 board. * * Carolyn Smith, Tektronix, Inc. * * This code is GPLed * * $Id: sbc8240.c,v 1.2 2003/09/30 19:37:00 thayne Exp $ * *//* * The SBC8240 has 2 flash banks. * Bank 0 is a 512 KiB AMD AM29F040B; 8 x 64 KiB sectors. * It contains the U-Boot code (7 sectors) and the environment (1 sector). * Bank 1 is 4 x 1 MiB AMD AM29LV800BT; 15 x 64 KiB sectors, 1 x 32 KiB sector, * 2 x 8 KiB sectors, 1 x 16 KiB sectors. * Both parts are JEDEC compatible. */#include <linux/config.h>#include <linux/module.h>#include <linux/types.h>#include <linux/kernel.h>#include <asm/io.h>#include <linux/mtd/mtd.h>#include <linux/mtd/map.h>#include <linux/mtd/cfi.h>#ifdef CONFIG_MTD_PARTITIONS#include <linux/mtd/partitions.h>#endif#define	DEBUG#ifdef	DEBUG# define debugk(fmt,args...)	printk(fmt ,##args)#else# define debugk(fmt,args...)#endif#define WINDOW_ADDR0	0xFFF00000		/* 512 KiB */#define WINDOW_SIZE0	0x00080000#define BUSWIDTH0	1#define WINDOW_ADDR1	0xFF000000		/* 4 MiB */#define WINDOW_SIZE1	0x00400000#define BUSWIDTH1	8#define MSG_PREFIX "sbc8240:"	/* prefix for our printk()'s */#define MTDID	   "sbc8240-%d"	/* for mtdparts= partitioning */static __u8 sbc8240_read8 (struct map_info *map, unsigned long ofs){	return __raw_readb(map->map_priv_1 + ofs);}static __u16 sbc8240_read16 (struct map_info *map, unsigned long ofs){	return __raw_readw(map->map_priv_1 + ofs);}static __u32 sbc8240_read32 (struct map_info *map, unsigned long ofs){	return __raw_readl(map->map_priv_1 + ofs);}unsigned long long result64;static __u64 sbc8240_read64 (struct map_info *map, unsigned long ofs){	unsigned long flags, msr, saved_msr;	volatile long saved_fr[2];	volatile unsigned long long result;	volatile unsigned long *p;	save_flags(flags);	cli();	/* turn off floating point unavailable exceptions */	__asm__ __volatile__ (		"mfmsr %0" 		: "=r" (msr) :);	saved_msr = msr;	msr |= MSR_FP;	msr &= ~(MSR_FE0 | MSR_FE1);	__asm__ __volatile__ (		"mtmsr %0\n"		"isync\n"		: : "r" (msr));	/* read the data via a floating point register */	ofs = map->map_priv_1 + ofs;	p = (unsigned long *) &result64;	__asm__ __volatile__ (		"lfd  1,0(%1)\n"		"stfd 1,0(%0)\n"		: : "r" (p), "r" (ofs)		);	/* restore state */	__asm__ __volatile__ (		"mtmsr %0\n"		"isync\n"		: : "r" (saved_msr));	restore_flags(flags);	p = (unsigned long *) &result64;	debugk("sbc8240_read64 ofs 0x%x result 0x%08x%08x\n", ofs, *p, *(p+1));	return result64;}static void sbc8240_copy_from (struct map_info *map,			       void *to, unsigned long from, ssize_t len){	memcpy_fromio (to, (void *) (map->map_priv_1 + from), len);}static void sbc8240_write8 (struct map_info *map, __u8 d, unsigned long adr){	__raw_writeb(d, map->map_priv_1 + adr);	mb();}static void sbc8240_write16 (struct map_info *map, __u16 d,			     unsigned long adr){	__raw_writew(d, map->map_priv_1 + adr);	mb();}static void sbc8240_write32 (struct map_info *map, __u32 d,			     unsigned long adr){	__raw_writel(d, map->map_priv_1 + adr);	mb();}static void sbc8240_write64 (struct map_info *map, __u64 data,			     unsigned long adr){	unsigned long long tmp;	unsigned long flags, msr, saved_msr, *p;	volatile long saved_fr[2];	save_flags(flags);	cli();	/* turn off floating point unavailable exceptions */	__asm__ __volatile__ (		"mfmsr %0" 		: "=r" (msr) :);	saved_msr = msr;	msr |= MSR_FP;	msr &= ~(MSR_FE0 | MSR_FE1);	__asm__ __volatile__ (		"mtmsr %0\n"		"isync\n"		: : "r" (msr));	/* write the data via a floating point register */	tmp = data;	p = (unsigned long *) &tmp;	adr = map->map_priv_1 + adr;	debugk("sbc8240_write64 adr 0x%x data 0x%08x%08x\n", adr, *p, *(p+1));	__asm__ __volatile__ (		"stfd 1,0(%2)\n"		"lfd  1,0(%0)\n"		"stfd 1,0(%1)\n"		"lfd  1,0(%2)\n"		: : "r" (p), "r" (adr), "b" (saved_fr)		);	/* restore state */	__asm__ __volatile__ (		"mtmsr %0\n"		"isync\n"		: : "r" (saved_msr));	restore_flags(flags);}static void sbc8240_copy_to (struct map_info *map,			     unsigned long to, const void *from, ssize_t len){	memcpy_toio ((void *) (map->map_priv_1 + to), from, len);}static struct map_info sbc8240_map[2] = {	{		.name           = "sbc8240 Flash Bank #0",		.size           = WINDOW_SIZE0,		.buswidth       = BUSWIDTH0,		.read8          = sbc8240_read8,		.read16         = sbc8240_read16,		.read32         = sbc8240_read32,		.read64         = sbc8240_read64,		.copy_from      = sbc8240_copy_from,		.write8         = sbc8240_write8,		.write16        = sbc8240_write16,		.write32        = sbc8240_write32,		.write64        = sbc8240_write64,		.copy_to        = sbc8240_copy_to	},	{		.name           = "sbc8240 Flash Bank #1",		.size           = WINDOW_SIZE1,		.buswidth       = BUSWIDTH1,		.read8          = sbc8240_read8,		.read16         = sbc8240_read16,		.read32         = sbc8240_read32,		.read64         = sbc8240_read64,		.copy_from      = sbc8240_copy_from,		.write8         = sbc8240_write8,		.write16        = sbc8240_write16,		.write32        = sbc8240_write32,		.write64        = sbc8240_write64,		.copy_to        = sbc8240_copy_to	}};#define NUM_FLASH_BANKS	(sizeof(sbc8240_map) / sizeof(struct map_info))/* * The following defines the partition layout of SBC8240 boards. * * See include/linux/mtd/partitions.h for definition of the * mtd_partition structure. * * The *_max_flash_size is the maximum possible mapped flash size * which is not necessarily the actual flash size. It must correspond * to the value specified in the mapping definition defined by the * "struct map_desc *_io_desc" for the corresponding machine. */#ifdef CONFIG_MTD_PARTITIONSstatic struct mtd_partition sbc8240_uboot_partitions [] = {	/* Bank 0 */	{		.name =	"U-boot",			/* U-Boot Firmware	*/		.offset =	0,		.size =	0x00070000,			/*  7 x 64 KiB sectors 	*/		.mask_flags = MTD_WRITEABLE,		/*  force read-only	*/	},	{		.name =	"environment",			/* U-Boot environment	*/		.offset =	0x00070000,		.size =	0x00010000,			/*  1 x 64 KiB sector	*/	},};static struct mtd_partition sbc8240_fs_partitions [] = {	{		.name =	"jffs",				/* JFFS  filesystem	*/		.offset =	0,		.size =	0x003C0000,			/*  4 * 15 * 64KiB	*/	},	{		.name =	"tmp32",		.offset =	0x003C0000,		.size =	0x00020000,			/*  4 * 32KiB		*/	},	{		.name =	"tmp8a",		.offset =	0x003E0000,		.size =	0x00008000,			/*  4 * 8KiB		*/	},	{		.name =	"tmp8b",		.offset =	0x003E8000,		.size =	0x00008000,			/*  4 * 8KiB		*/	},	{		.name =	"tmp16",		.offset =	0x003F0000,		.size =	0x00010000,			/*  4 * 16KiB		*/	}};#define NB_OF(x) (sizeof (x) / sizeof (x[0]))/* trivial struct to describe partition information */struct mtd_part_def{	int nums;	unsigned char *type;	struct mtd_partition* mtd_part;};static struct mtd_info *sbc8240_mtd[NUM_FLASH_BANKS];static struct mtd_part_def sbc8240_part_banks[NUM_FLASH_BANKS];#endif	/* CONFIG_MTD_PARTITIONS */int __init init_sbc8240_mtd (void){	static struct _cjs {		u_long addr;		u_long size;	} pt[NUM_FLASH_BANKS] = {		{			.addr = WINDOW_ADDR0,			.size = WINDOW_SIZE0		},		{			.addr = WINDOW_ADDR1,			.size = WINDOW_SIZE1		},	};	int devicesfound = 0;	int i;	for (i = 0; i < NUM_FLASH_BANKS; i++) {		printk (KERN_NOTICE MSG_PREFIX			"Probing 0x%08lx at 0x%08lx\n", pt[i].size, pt[i].addr);		sbc8240_map[i].map_priv_1 =			(unsigned long) ioremap (pt[i].addr, pt[i].size);		if (!sbc8240_map[i].map_priv_1) {			printk (MSG_PREFIX "failed to ioremap\n");			return -EIO;		}		sbc8240_mtd[i] = do_map_probe("jedec_probe", &sbc8240_map[i]);		if (sbc8240_mtd[i]) {			sbc8240_mtd[i]->module = THIS_MODULE;			devicesfound++;		}	}	if (!devicesfound) {		printk(KERN_NOTICE MSG_PREFIX		       "No suppported flash chips found!\n");		return -ENXIO;	}#ifdef CONFIG_MTD_PARTITIONS	sbc8240_part_banks[0].mtd_part   = sbc8240_uboot_partitions;	sbc8240_part_banks[0].type       = "static image";	sbc8240_part_banks[0].nums       = NB_OF(sbc8240_uboot_partitions);	sbc8240_part_banks[1].mtd_part   = sbc8240_fs_partitions;	sbc8240_part_banks[1].type       = "static file system";	sbc8240_part_banks[1].nums       = NB_OF(sbc8240_fs_partitions);	for (i = 0; i < NUM_FLASH_BANKS; i++) {		if (!sbc8240_mtd[i]) continue;		if (sbc8240_part_banks[i].nums == 0) {			printk (KERN_NOTICE MSG_PREFIX				"No partition info available, registering whole device\n");			add_mtd_device(sbc8240_mtd[i]);		} else {			printk (KERN_NOTICE MSG_PREFIX				"Using %s partition definition\n", sbc8240_part_banks[i].mtd_part->name);			add_mtd_partitions (sbc8240_mtd[i], 					    sbc8240_part_banks[i].mtd_part,					    sbc8240_part_banks[i].nums);		}	}#else	printk(KERN_NOTICE MSG_PREFIX	       "Registering %d flash banks at once\n", devicesfound);	for (i = 0; i < devicesfound; i++) {		add_mtd_device(sbc8240_mtd[i]);	}#endif	/* CONFIG_MTD_PARTITIONS */	return devicesfound == 0 ? -ENXIO : 0;}static void __exit cleanup_sbc8240_mtd (void){	int i;	for (i = 0; i < NUM_FLASH_BANKS; i++) {		if (sbc8240_mtd[i]) {			del_mtd_device (sbc8240_mtd[i]);			map_destroy (sbc8240_mtd[i]);		}		if (sbc8240_map[i].map_priv_1) {			iounmap ((void *) sbc8240_map[i].map_priv_1);			sbc8240_map[i].map_priv_1 = 0;		}	}}module_init (init_sbc8240_mtd);module_exit (cleanup_sbc8240_mtd);MODULE_LICENSE ("GPL");MODULE_AUTHOR ("Carolyn Smith <carolyn.smith@tektronix.com>");MODULE_DESCRIPTION ("MTD map driver for SBC8240 boards");

⌨️ 快捷键说明

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