1/* fortunet.c memory map 2 * 3 * $Id: fortunet.c,v 1.1.1.1 2007/08/03 18:52:43 Exp $ 4 */ 5 6#include <linux/module.h> 7#include <linux/types.h> 8#include <linux/kernel.h> 9#include <linux/init.h> 10#include <linux/string.h> 11 12#include <linux/mtd/mtd.h> 13#include <linux/mtd/map.h> 14#include <linux/mtd/partitions.h> 15 16#include <asm/io.h> 17 18#define MAX_NUM_REGIONS 4 19#define MAX_NUM_PARTITIONS 8 20 21#define DEF_WINDOW_ADDR_PHY 0x00000000 22#define DEF_WINDOW_SIZE 0x00800000 // 8 Mega Bytes 23 24#define MTD_FORTUNET_PK "MTD FortuNet: " 25 26#define MAX_NAME_SIZE 128 27 28struct map_region 29{ 30 int window_addr_physical; 31 int altbankwidth; 32 struct map_info map_info; 33 struct mtd_info *mymtd; 34 struct mtd_partition parts[MAX_NUM_PARTITIONS]; 35 char map_name[MAX_NAME_SIZE]; 36 char parts_name[MAX_NUM_PARTITIONS][MAX_NAME_SIZE]; 37}; 38 39static struct map_region map_regions[MAX_NUM_REGIONS]; 40static int map_regions_set[MAX_NUM_REGIONS] = {0,0,0,0}; 41static int map_regions_parts[MAX_NUM_REGIONS] = {0,0,0,0}; 42 43 44 45struct map_info default_map = { 46 .size = DEF_WINDOW_SIZE, 47 .bankwidth = 4, 48}; 49 50static char * __init get_string_option(char *dest,int dest_size,char *sor) 51{ 52 if(!dest_size) 53 return sor; 54 dest_size--; 55 while(*sor) 56 { 57 if(*sor==',') 58 { 59 sor++; 60 break; 61 } 62 else if(*sor=='\"') 63 { 64 sor++; 65 while(*sor) 66 { 67 if(*sor=='\"') 68 { 69 sor++; 70 break; 71 } 72 *dest = *sor; 73 dest++; 74 sor++; 75 dest_size--; 76 if(!dest_size) 77 { 78 *dest = 0; 79 return sor; 80 } 81 } 82 } 83 else 84 { 85 *dest = *sor; 86 dest++; 87 sor++; 88 dest_size--; 89 if(!dest_size) 90 { 91 *dest = 0; 92 return sor; 93 } 94 } 95 } 96 *dest = 0; 97 return sor; 98} 99 100static int __init MTD_New_Region(char *line) 101{ 102 char string[MAX_NAME_SIZE]; 103 int params[6]; 104 get_options (get_string_option(string,sizeof(string),line),6,params); 105 if(params[0]<1) 106 { 107 printk(MTD_FORTUNET_PK "Bad parameters for MTD Region " 108 " name,region-number[,base,size,bankwidth,altbankwidth]\n"); 109 return 1; 110 } 111 if((params[1]<0)||(params[1]>=MAX_NUM_REGIONS)) 112 { 113 printk(MTD_FORTUNET_PK "Bad region index of %d only have 0..%u regions\n", 114 params[1],MAX_NUM_REGIONS-1); 115 return 1; 116 } 117 memset(&map_regions[params[1]],0,sizeof(map_regions[params[1]])); 118 memcpy(&map_regions[params[1]].map_info, 119 &default_map,sizeof(map_regions[params[1]].map_info)); 120 map_regions_set[params[1]] = 1; 121 map_regions[params[1]].window_addr_physical = DEF_WINDOW_ADDR_PHY; 122 map_regions[params[1]].altbankwidth = 2; 123 map_regions[params[1]].mymtd = NULL; 124 map_regions[params[1]].map_info.name = map_regions[params[1]].map_name; 125 strcpy(map_regions[params[1]].map_info.name,string); 126 if(params[0]>1) 127 { 128 map_regions[params[1]].window_addr_physical = params[2]; 129 } 130 if(params[0]>2) 131 { 132 map_regions[params[1]].map_info.size = params[3]; 133 } 134 if(params[0]>3) 135 { 136 map_regions[params[1]].map_info.bankwidth = params[4]; 137 } 138 if(params[0]>4) 139 { 140 map_regions[params[1]].altbankwidth = params[5]; 141 } 142 return 1; 143} 144 145static int __init MTD_New_Partition(char *line) 146{ 147 char string[MAX_NAME_SIZE]; 148 int params[4]; 149 get_options (get_string_option(string,sizeof(string),line),4,params); 150 if(params[0]<3) 151 { 152 printk(MTD_FORTUNET_PK "Bad parameters for MTD Partition " 153 " name,region-number,size,offset\n"); 154 return 1; 155 } 156 if((params[1]<0)||(params[1]>=MAX_NUM_REGIONS)) 157 { 158 printk(MTD_FORTUNET_PK "Bad region index of %d only have 0..%u regions\n", 159 params[1],MAX_NUM_REGIONS-1); 160 return 1; 161 } 162 if(map_regions_parts[params[1]]>=MAX_NUM_PARTITIONS) 163 { 164 printk(MTD_FORTUNET_PK "Out of space for partition in this region\n"); 165 return 1; 166 } 167 map_regions[params[1]].parts[map_regions_parts[params[1]]].name = 168 map_regions[params[1]]. parts_name[map_regions_parts[params[1]]]; 169 strcpy(map_regions[params[1]].parts[map_regions_parts[params[1]]].name,string); 170 map_regions[params[1]].parts[map_regions_parts[params[1]]].size = 171 params[2]; 172 map_regions[params[1]].parts[map_regions_parts[params[1]]].offset = 173 params[3]; 174 map_regions[params[1]].parts[map_regions_parts[params[1]]].mask_flags = 0; 175 map_regions_parts[params[1]]++; 176 return 1; 177} 178 179__setup("MTD_Region=", MTD_New_Region); 180__setup("MTD_Partition=", MTD_New_Partition); 181 182/* Backwards-spelling-compatibility */ 183__setup("MTD_Partion=", MTD_New_Partition); 184 185int __init init_fortunet(void) 186{ 187 int ix,iy; 188 for(iy=ix=0;ix<MAX_NUM_REGIONS;ix++) 189 { 190 if(map_regions_parts[ix]&&(!map_regions_set[ix])) 191 { 192 printk(MTD_FORTUNET_PK "Region %d is not setup (Setting to default)\n", 193 ix); 194 memset(&map_regions[ix],0,sizeof(map_regions[ix])); 195 memcpy(&map_regions[ix].map_info,&default_map, 196 sizeof(map_regions[ix].map_info)); 197 map_regions_set[ix] = 1; 198 map_regions[ix].window_addr_physical = DEF_WINDOW_ADDR_PHY; 199 map_regions[ix].altbankwidth = 2; 200 map_regions[ix].mymtd = NULL; 201 map_regions[ix].map_info.name = map_regions[ix].map_name; 202 strcpy(map_regions[ix].map_info.name,"FORTUNET"); 203 } 204 if(map_regions_set[ix]) 205 { 206 iy++; 207 printk(KERN_NOTICE MTD_FORTUNET_PK "%s flash device at physically " 208 " address %x size %x\n", 209 map_regions[ix].map_info.name, 210 map_regions[ix].window_addr_physical, 211 map_regions[ix].map_info.size); 212 213 map_regions[ix].map_info.phys = map_regions[ix].window_addr_physical, 214 215 map_regions[ix].map_info.virt = 216 ioremap_nocache( 217 map_regions[ix].window_addr_physical, 218 map_regions[ix].map_info.size); 219 if(!map_regions[ix].map_info.virt) 220 { 221 int j = 0; 222 printk(MTD_FORTUNET_PK "%s flash failed to ioremap!\n", 223 map_regions[ix].map_info.name); 224 for (j = 0 ; j < ix; j++) 225 iounmap(map_regions[j].map_info.virt); 226 return -ENXIO; 227 } 228 simple_map_init(&map_regions[ix].map_info); 229 230 printk(KERN_NOTICE MTD_FORTUNET_PK "%s flash is virtually at: %x\n", 231 map_regions[ix].map_info.name, 232 map_regions[ix].map_info.virt); 233 map_regions[ix].mymtd = do_map_probe("cfi_probe", 234 &map_regions[ix].map_info); 235 if((!map_regions[ix].mymtd)&&( 236 map_regions[ix].altbankwidth!=map_regions[ix].map_info.bankwidth)) 237 { 238 printk(KERN_NOTICE MTD_FORTUNET_PK "Trying alternate bankwidth " 239 "for %s flash.\n", 240 map_regions[ix].map_info.name); 241 map_regions[ix].map_info.bankwidth = 242 map_regions[ix].altbankwidth; 243 map_regions[ix].mymtd = do_map_probe("cfi_probe", 244 &map_regions[ix].map_info); 245 } 246 map_regions[ix].mymtd->owner = THIS_MODULE; 247 add_mtd_partitions(map_regions[ix].mymtd, 248 map_regions[ix].parts,map_regions_parts[ix]); 249 } 250 } 251 if(iy) 252 return 0; 253 return -ENXIO; 254} 255 256static void __exit cleanup_fortunet(void) 257{ 258 int ix; 259 for(ix=0;ix<MAX_NUM_REGIONS;ix++) 260 { 261 if(map_regions_set[ix]) 262 { 263 if( map_regions[ix].mymtd ) 264 { 265 del_mtd_partitions( map_regions[ix].mymtd ); 266 map_destroy( map_regions[ix].mymtd ); 267 } 268 iounmap((void *)map_regions[ix].map_info.virt); 269 } 270 } 271} 272 273module_init(init_fortunet); 274module_exit(cleanup_fortunet); 275 276MODULE_AUTHOR("FortuNet, Inc."); 277MODULE_DESCRIPTION("MTD map driver for FortuNet boards"); 278