| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /* | 
 | 2 |  * Handle mapping of the flash memory access routines on the SBC8240 board. | 
 | 3 |  * | 
 | 4 |  * Carolyn Smith, Tektronix, Inc. | 
 | 5 |  * | 
 | 6 |  * This code is GPLed | 
 | 7 |  * | 
| Thomas Gleixner | 69f34c9 | 2005-11-07 11:15:40 +0000 | [diff] [blame] | 8 |  * $Id: sbc8240.c,v 1.5 2005/11/07 11:14:28 gleixner Exp $ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 9 |  * | 
 | 10 |  */ | 
 | 11 |  | 
 | 12 | /* | 
 | 13 |  * The SBC8240 has 2 flash banks. | 
 | 14 |  * Bank 0 is a 512 KiB AMD AM29F040B; 8 x 64 KiB sectors. | 
 | 15 |  * It contains the U-Boot code (7 sectors) and the environment (1 sector). | 
 | 16 |  * Bank 1 is 4 x 1 MiB AMD AM29LV800BT; 15 x 64 KiB sectors, 1 x 32 KiB sector, | 
 | 17 |  * 2 x 8 KiB sectors, 1 x 16 KiB sectors. | 
 | 18 |  * Both parts are JEDEC compatible. | 
 | 19 |  */ | 
 | 20 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 21 | #include <linux/module.h> | 
 | 22 | #include <linux/types.h> | 
 | 23 | #include <linux/kernel.h> | 
 | 24 | #include <asm/io.h> | 
 | 25 |  | 
 | 26 | #include <linux/mtd/mtd.h> | 
 | 27 | #include <linux/mtd/map.h> | 
 | 28 | #include <linux/mtd/cfi.h> | 
 | 29 |  | 
 | 30 | #ifdef CONFIG_MTD_PARTITIONS | 
 | 31 | #include <linux/mtd/partitions.h> | 
 | 32 | #endif | 
 | 33 |  | 
 | 34 | #define	DEBUG | 
 | 35 |  | 
 | 36 | #ifdef	DEBUG | 
 | 37 | # define debugk(fmt,args...)	printk(fmt ,##args) | 
 | 38 | #else | 
 | 39 | # define debugk(fmt,args...) | 
 | 40 | #endif | 
 | 41 |  | 
 | 42 |  | 
 | 43 | #define WINDOW_ADDR0	0xFFF00000		/* 512 KiB */ | 
 | 44 | #define WINDOW_SIZE0	0x00080000 | 
 | 45 | #define BUSWIDTH0	1 | 
 | 46 |  | 
 | 47 | #define WINDOW_ADDR1	0xFF000000		/* 4 MiB */ | 
 | 48 | #define WINDOW_SIZE1	0x00400000 | 
 | 49 | #define BUSWIDTH1	8 | 
 | 50 |  | 
 | 51 | #define MSG_PREFIX "sbc8240:"	/* prefix for our printk()'s */ | 
 | 52 | #define MTDID	   "sbc8240-%d"	/* for mtdparts= partitioning */ | 
 | 53 |  | 
 | 54 |  | 
 | 55 | static struct map_info sbc8240_map[2] = { | 
 | 56 | 	{ | 
 | 57 | 		.name           = "sbc8240 Flash Bank #0", | 
 | 58 | 		.size           = WINDOW_SIZE0, | 
 | 59 | 		.bankwidth       = BUSWIDTH0, | 
 | 60 | 	}, | 
 | 61 | 	{ | 
 | 62 | 		.name           = "sbc8240 Flash Bank #1", | 
 | 63 | 		.size           = WINDOW_SIZE1, | 
 | 64 | 		.bankwidth       = BUSWIDTH1, | 
 | 65 | 	} | 
 | 66 | }; | 
 | 67 |  | 
| Tobias Klauser | 87d10f3 | 2006-03-31 02:29:45 -0800 | [diff] [blame] | 68 | #define NUM_FLASH_BANKS	ARRAY_SIZE(sbc8240_map) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 69 |  | 
 | 70 | /* | 
 | 71 |  * The following defines the partition layout of SBC8240 boards. | 
 | 72 |  * | 
 | 73 |  * See include/linux/mtd/partitions.h for definition of the | 
 | 74 |  * mtd_partition structure. | 
 | 75 |  * | 
 | 76 |  * The *_max_flash_size is the maximum possible mapped flash size | 
 | 77 |  * which is not necessarily the actual flash size. It must correspond | 
 | 78 |  * to the value specified in the mapping definition defined by the | 
 | 79 |  * "struct map_desc *_io_desc" for the corresponding machine. | 
 | 80 |  */ | 
 | 81 |  | 
 | 82 | #ifdef CONFIG_MTD_PARTITIONS | 
 | 83 |  | 
 | 84 | static struct mtd_partition sbc8240_uboot_partitions [] = { | 
 | 85 | 	/* Bank 0 */ | 
 | 86 | 	{ | 
 | 87 | 		.name =	"U-boot",			/* U-Boot Firmware	*/ | 
 | 88 | 		.offset =	0, | 
 | 89 | 		.size =	0x00070000,			/*  7 x 64 KiB sectors 	*/ | 
 | 90 | 		.mask_flags = MTD_WRITEABLE,		/*  force read-only	*/ | 
 | 91 | 	}, | 
 | 92 | 	{ | 
 | 93 | 		.name =	"environment",			/* U-Boot environment	*/ | 
 | 94 | 		.offset =	0x00070000, | 
 | 95 | 		.size =	0x00010000,			/*  1 x 64 KiB sector	*/ | 
 | 96 | 	}, | 
 | 97 | }; | 
 | 98 |  | 
 | 99 | static struct mtd_partition sbc8240_fs_partitions [] = { | 
 | 100 | 	{ | 
 | 101 | 		.name =	"jffs",				/* JFFS  filesystem	*/ | 
 | 102 | 		.offset =	0, | 
 | 103 | 		.size =	0x003C0000,			/*  4 * 15 * 64KiB	*/ | 
 | 104 | 	}, | 
 | 105 | 	{ | 
 | 106 | 		.name =	"tmp32", | 
 | 107 | 		.offset =	0x003C0000, | 
 | 108 | 		.size =	0x00020000,			/*  4 * 32KiB		*/ | 
 | 109 | 	}, | 
 | 110 | 	{ | 
 | 111 | 		.name =	"tmp8a", | 
 | 112 | 		.offset =	0x003E0000, | 
 | 113 | 		.size =	0x00008000,			/*  4 * 8KiB		*/ | 
 | 114 | 	}, | 
 | 115 | 	{ | 
 | 116 | 		.name =	"tmp8b", | 
 | 117 | 		.offset =	0x003E8000, | 
 | 118 | 		.size =	0x00008000,			/*  4 * 8KiB		*/ | 
 | 119 | 	}, | 
 | 120 | 	{ | 
 | 121 | 		.name =	"tmp16", | 
 | 122 | 		.offset =	0x003F0000, | 
 | 123 | 		.size =	0x00010000,			/*  4 * 16KiB		*/ | 
 | 124 | 	} | 
 | 125 | }; | 
 | 126 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 127 | /* trivial struct to describe partition information */ | 
 | 128 | struct mtd_part_def | 
 | 129 | { | 
 | 130 | 	int nums; | 
 | 131 | 	unsigned char *type; | 
 | 132 | 	struct mtd_partition* mtd_part; | 
 | 133 | }; | 
 | 134 |  | 
 | 135 | static struct mtd_info *sbc8240_mtd[NUM_FLASH_BANKS]; | 
 | 136 | static struct mtd_part_def sbc8240_part_banks[NUM_FLASH_BANKS]; | 
 | 137 |  | 
 | 138 |  | 
 | 139 | #endif	/* CONFIG_MTD_PARTITIONS */ | 
 | 140 |  | 
 | 141 |  | 
 | 142 | int __init init_sbc8240_mtd (void) | 
 | 143 | { | 
 | 144 | 	static struct _cjs { | 
 | 145 | 		u_long addr; | 
 | 146 | 		u_long size; | 
 | 147 | 	} pt[NUM_FLASH_BANKS] = { | 
 | 148 | 		{ | 
 | 149 | 			.addr = WINDOW_ADDR0, | 
 | 150 | 			.size = WINDOW_SIZE0 | 
 | 151 | 		}, | 
 | 152 | 		{ | 
 | 153 | 			.addr = WINDOW_ADDR1, | 
 | 154 | 			.size = WINDOW_SIZE1 | 
 | 155 | 		}, | 
 | 156 | 	}; | 
 | 157 |  | 
 | 158 | 	int devicesfound = 0; | 
| Amol Lad | 25f0c65 | 2006-09-21 18:12:43 +0530 | [diff] [blame] | 159 | 	int i,j; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 160 |  | 
 | 161 | 	for (i = 0; i < NUM_FLASH_BANKS; i++) { | 
 | 162 | 		printk (KERN_NOTICE MSG_PREFIX | 
 | 163 | 			"Probing 0x%08lx at 0x%08lx\n", pt[i].size, pt[i].addr); | 
 | 164 |  | 
 | 165 | 		sbc8240_map[i].map_priv_1 = | 
 | 166 | 			(unsigned long) ioremap (pt[i].addr, pt[i].size); | 
 | 167 | 		if (!sbc8240_map[i].map_priv_1) { | 
 | 168 | 			printk (MSG_PREFIX "failed to ioremap\n"); | 
| Amol Lad | 25f0c65 | 2006-09-21 18:12:43 +0530 | [diff] [blame] | 169 | 			for (j = 0; j < i; j++) { | 
 | 170 | 				iounmap((void *) sbc8240_map[j].map_priv_1); | 
 | 171 | 				sbc8240_map[j].map_priv_1 = 0; | 
 | 172 | 			} | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 173 | 			return -EIO; | 
 | 174 | 		} | 
 | 175 | 		simple_map_init(&sbc8240_mtd[i]); | 
 | 176 |  | 
 | 177 | 		sbc8240_mtd[i] = do_map_probe("jedec_probe", &sbc8240_map[i]); | 
 | 178 |  | 
 | 179 | 		if (sbc8240_mtd[i]) { | 
 | 180 | 			sbc8240_mtd[i]->module = THIS_MODULE; | 
 | 181 | 			devicesfound++; | 
| Amol Lad | 25f0c65 | 2006-09-21 18:12:43 +0530 | [diff] [blame] | 182 | 		} else { | 
 | 183 | 			if (sbc8240_map[i].map_priv_1) { | 
 | 184 | 				iounmap((void *) sbc8240_map[i].map_priv_1); | 
 | 185 | 				sbc8240_map[i].map_priv_1 = 0; | 
 | 186 | 			} | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 187 | 		} | 
 | 188 | 	} | 
 | 189 |  | 
 | 190 | 	if (!devicesfound) { | 
 | 191 | 		printk(KERN_NOTICE MSG_PREFIX | 
 | 192 | 		       "No suppported flash chips found!\n"); | 
 | 193 | 		return -ENXIO; | 
 | 194 | 	} | 
 | 195 |  | 
 | 196 | #ifdef CONFIG_MTD_PARTITIONS | 
 | 197 | 	sbc8240_part_banks[0].mtd_part   = sbc8240_uboot_partitions; | 
 | 198 | 	sbc8240_part_banks[0].type       = "static image"; | 
| Tobias Klauser | 87d10f3 | 2006-03-31 02:29:45 -0800 | [diff] [blame] | 199 | 	sbc8240_part_banks[0].nums       = ARRAY_SIZE(sbc8240_uboot_partitions); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 200 | 	sbc8240_part_banks[1].mtd_part   = sbc8240_fs_partitions; | 
 | 201 | 	sbc8240_part_banks[1].type       = "static file system"; | 
| Tobias Klauser | 87d10f3 | 2006-03-31 02:29:45 -0800 | [diff] [blame] | 202 | 	sbc8240_part_banks[1].nums       = ARRAY_SIZE(sbc8240_fs_partitions); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 203 |  | 
 | 204 | 	for (i = 0; i < NUM_FLASH_BANKS; i++) { | 
 | 205 |  | 
 | 206 | 		if (!sbc8240_mtd[i]) continue; | 
 | 207 | 		if (sbc8240_part_banks[i].nums == 0) { | 
 | 208 | 			printk (KERN_NOTICE MSG_PREFIX | 
 | 209 | 				"No partition info available, registering whole device\n"); | 
 | 210 | 			add_mtd_device(sbc8240_mtd[i]); | 
 | 211 | 		} else { | 
 | 212 | 			printk (KERN_NOTICE MSG_PREFIX | 
 | 213 | 				"Using %s partition definition\n", sbc8240_part_banks[i].mtd_part->name); | 
| Thomas Gleixner | 69f34c9 | 2005-11-07 11:15:40 +0000 | [diff] [blame] | 214 | 			add_mtd_partitions (sbc8240_mtd[i], | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 215 | 					    sbc8240_part_banks[i].mtd_part, | 
 | 216 | 					    sbc8240_part_banks[i].nums); | 
 | 217 | 		} | 
 | 218 | 	} | 
 | 219 | #else | 
 | 220 | 	printk(KERN_NOTICE MSG_PREFIX | 
 | 221 | 	       "Registering %d flash banks at once\n", devicesfound); | 
 | 222 |  | 
 | 223 | 	for (i = 0; i < devicesfound; i++) { | 
 | 224 | 		add_mtd_device(sbc8240_mtd[i]); | 
 | 225 | 	} | 
 | 226 | #endif	/* CONFIG_MTD_PARTITIONS */ | 
 | 227 |  | 
 | 228 | 	return devicesfound == 0 ? -ENXIO : 0; | 
 | 229 | } | 
 | 230 |  | 
 | 231 | static void __exit cleanup_sbc8240_mtd (void) | 
 | 232 | { | 
 | 233 | 	int i; | 
 | 234 |  | 
 | 235 | 	for (i = 0; i < NUM_FLASH_BANKS; i++) { | 
 | 236 | 		if (sbc8240_mtd[i]) { | 
 | 237 | 			del_mtd_device (sbc8240_mtd[i]); | 
 | 238 | 			map_destroy (sbc8240_mtd[i]); | 
 | 239 | 		} | 
 | 240 | 		if (sbc8240_map[i].map_priv_1) { | 
 | 241 | 			iounmap ((void *) sbc8240_map[i].map_priv_1); | 
 | 242 | 			sbc8240_map[i].map_priv_1 = 0; | 
 | 243 | 		} | 
 | 244 | 	} | 
 | 245 | } | 
 | 246 |  | 
 | 247 | module_init (init_sbc8240_mtd); | 
 | 248 | module_exit (cleanup_sbc8240_mtd); | 
 | 249 |  | 
 | 250 | MODULE_LICENSE ("GPL"); | 
 | 251 | MODULE_AUTHOR ("Carolyn Smith <carolyn.smith@tektronix.com>"); | 
 | 252 | MODULE_DESCRIPTION ("MTD map driver for SBC8240 boards"); | 
 | 253 |  |