| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /* | 
|  | 2 | * Flash memory access on Alchemy Db1550 board | 
|  | 3 | * | 
|  | 4 | * $Id: db1550-flash.c,v 1.7 2004/11/04 13:24:14 gleixner Exp $ | 
|  | 5 | * | 
|  | 6 | * (C) 2004 Embedded Edge, LLC, based on db1550-flash.c: | 
|  | 7 | * (C) 2003, 2004 Pete Popov <ppopov@embeddedalley.com> | 
|  | 8 | * | 
|  | 9 | */ | 
|  | 10 |  | 
|  | 11 | #include <linux/config.h> | 
|  | 12 | #include <linux/init.h> | 
|  | 13 | #include <linux/module.h> | 
|  | 14 | #include <linux/types.h> | 
|  | 15 | #include <linux/kernel.h> | 
|  | 16 |  | 
|  | 17 | #include <linux/mtd/mtd.h> | 
|  | 18 | #include <linux/mtd/map.h> | 
|  | 19 | #include <linux/mtd/partitions.h> | 
|  | 20 |  | 
|  | 21 | #include <asm/io.h> | 
|  | 22 |  | 
|  | 23 | #ifdef 	DEBUG_RW | 
|  | 24 | #define	DBG(x...)	printk(x) | 
|  | 25 | #else | 
|  | 26 | #define	DBG(x...) | 
|  | 27 | #endif | 
|  | 28 |  | 
|  | 29 | static unsigned long window_addr; | 
|  | 30 | static unsigned long window_size; | 
|  | 31 |  | 
|  | 32 |  | 
|  | 33 | static struct map_info db1550_map = { | 
|  | 34 | .name =	"Db1550 flash", | 
|  | 35 | }; | 
|  | 36 |  | 
|  | 37 | static unsigned char flash_bankwidth = 4; | 
|  | 38 |  | 
|  | 39 | /* | 
|  | 40 | * Support only 64MB NOR Flash parts | 
|  | 41 | */ | 
|  | 42 |  | 
|  | 43 | #if defined(CONFIG_MTD_DB1550_BOOT) && defined(CONFIG_MTD_DB1550_USER) | 
|  | 44 | #define DB1550_BOTH_BANKS | 
|  | 45 | #elif defined(CONFIG_MTD_DB1550_BOOT) && !defined(CONFIG_MTD_DB1550_USER) | 
|  | 46 | #define DB1550_BOOT_ONLY | 
|  | 47 | #elif !defined(CONFIG_MTD_DB1550_BOOT) && defined(CONFIG_MTD_DB1550_USER) | 
|  | 48 | #define DB1550_USER_ONLY | 
|  | 49 | #endif | 
|  | 50 |  | 
|  | 51 | #ifdef DB1550_BOTH_BANKS | 
|  | 52 | /* both banks will be used. Combine the first bank and the first | 
|  | 53 | * part of the second bank together into a single jffs/jffs2 | 
|  | 54 | * partition. | 
|  | 55 | */ | 
|  | 56 | static struct mtd_partition db1550_partitions[] = { | 
|  | 57 | /* assume boot[2:0]:swap is '0000' or '1000', which translates to: | 
|  | 58 | * 1C00 0000 1FFF FFFF CE0 64MB Boot NOR Flash | 
|  | 59 | * 1800 0000 1BFF FFFF CE0 64MB Param NOR Flash | 
|  | 60 | */ | 
|  | 61 | { | 
|  | 62 | .name = "User FS", | 
|  | 63 | .size =   (0x1FC00000 - 0x18000000), | 
|  | 64 | .offset = 0x0000000 | 
|  | 65 | },{ | 
|  | 66 | .name = "yamon", | 
|  | 67 | .size = 0x0100000, | 
|  | 68 | .offset = MTDPART_OFS_APPEND, | 
|  | 69 | .mask_flags = MTD_WRITEABLE | 
|  | 70 | },{ | 
|  | 71 | .name = "raw kernel", | 
|  | 72 | .size = (0x300000 - 0x40000), /* last 256KB is yamon env */ | 
|  | 73 | .offset = MTDPART_OFS_APPEND, | 
|  | 74 | } | 
|  | 75 | }; | 
|  | 76 | #elif defined(DB1550_BOOT_ONLY) | 
|  | 77 | static struct mtd_partition db1550_partitions[] = { | 
|  | 78 | /* assume boot[2:0]:swap is '0000' or '1000', which translates to: | 
|  | 79 | * 1C00 0000 1FFF FFFF CE0 64MB Boot NOR Flash | 
|  | 80 | */ | 
|  | 81 | { | 
|  | 82 | .name = "User FS", | 
|  | 83 | .size =   0x03c00000, | 
|  | 84 | .offset = 0x0000000 | 
|  | 85 | },{ | 
|  | 86 | .name = "yamon", | 
|  | 87 | .size = 0x0100000, | 
|  | 88 | .offset = MTDPART_OFS_APPEND, | 
|  | 89 | .mask_flags = MTD_WRITEABLE | 
|  | 90 | },{ | 
|  | 91 | .name = "raw kernel", | 
|  | 92 | .size = (0x300000-0x40000), /* last 256KB is yamon env */ | 
|  | 93 | .offset = MTDPART_OFS_APPEND, | 
|  | 94 | } | 
|  | 95 | }; | 
|  | 96 | #elif defined(DB1550_USER_ONLY) | 
|  | 97 | static struct mtd_partition db1550_partitions[] = { | 
|  | 98 | /* assume boot[2:0]:swap is '0000' or '1000', which translates to: | 
|  | 99 | * 1800 0000 1BFF FFFF CE0 64MB Param NOR Flash | 
|  | 100 | */ | 
|  | 101 | { | 
|  | 102 | .name = "User FS", | 
|  | 103 | .size = (0x4000000 - 0x200000), /* reserve 2MB for raw kernel */ | 
|  | 104 | .offset = 0x0000000 | 
|  | 105 | },{ | 
|  | 106 | .name = "raw kernel", | 
|  | 107 | .size = MTDPART_SIZ_FULL, | 
|  | 108 | .offset = MTDPART_OFS_APPEND, | 
|  | 109 | } | 
|  | 110 | }; | 
|  | 111 | #else | 
|  | 112 | #error MTD_DB1550 define combo error /* should never happen */ | 
|  | 113 | #endif | 
|  | 114 |  | 
|  | 115 | #define NB_OF(x)  (sizeof(x)/sizeof(x[0])) | 
|  | 116 |  | 
|  | 117 | static struct mtd_info *mymtd; | 
|  | 118 |  | 
|  | 119 | /* | 
|  | 120 | * Probe the flash density and setup window address and size | 
|  | 121 | * based on user CONFIG options. There are times when we don't | 
|  | 122 | * want the MTD driver to be probing the boot or user flash, | 
|  | 123 | * so having the option to enable only one bank is important. | 
|  | 124 | */ | 
|  | 125 | int setup_flash_params(void) | 
|  | 126 | { | 
|  | 127 | #if defined(DB1550_BOTH_BANKS) | 
|  | 128 | window_addr = 0x18000000; | 
|  | 129 | window_size = 0x8000000; | 
|  | 130 | #elif defined(DB1550_BOOT_ONLY) | 
|  | 131 | window_addr = 0x1C000000; | 
|  | 132 | window_size = 0x4000000; | 
|  | 133 | #else /* USER ONLY */ | 
|  | 134 | window_addr = 0x18000000; | 
|  | 135 | window_size = 0x4000000; | 
|  | 136 | #endif | 
|  | 137 | return 0; | 
|  | 138 | } | 
|  | 139 |  | 
|  | 140 | int __init db1550_mtd_init(void) | 
|  | 141 | { | 
|  | 142 | struct mtd_partition *parts; | 
|  | 143 | int nb_parts = 0; | 
|  | 144 |  | 
|  | 145 | /* Default flash bankwidth */ | 
|  | 146 | db1550_map.bankwidth = flash_bankwidth; | 
|  | 147 |  | 
|  | 148 | if (setup_flash_params()) | 
|  | 149 | return -ENXIO; | 
|  | 150 |  | 
|  | 151 | /* | 
|  | 152 | * Static partition definition selection | 
|  | 153 | */ | 
|  | 154 | parts = db1550_partitions; | 
|  | 155 | nb_parts = NB_OF(db1550_partitions); | 
|  | 156 | db1550_map.size = window_size; | 
|  | 157 |  | 
|  | 158 | /* | 
|  | 159 | * Now let's probe for the actual flash.  Do it here since | 
|  | 160 | * specific machine settings might have been set above. | 
|  | 161 | */ | 
|  | 162 | printk(KERN_NOTICE "Db1550 flash: probing %d-bit flash bus\n", | 
|  | 163 | db1550_map.bankwidth*8); | 
|  | 164 | db1550_map.virt = ioremap(window_addr, window_size); | 
|  | 165 | mymtd = do_map_probe("cfi_probe", &db1550_map); | 
|  | 166 | if (!mymtd) return -ENXIO; | 
|  | 167 | mymtd->owner = THIS_MODULE; | 
|  | 168 |  | 
|  | 169 | add_mtd_partitions(mymtd, parts, nb_parts); | 
|  | 170 | return 0; | 
|  | 171 | } | 
|  | 172 |  | 
|  | 173 | static void __exit db1550_mtd_cleanup(void) | 
|  | 174 | { | 
|  | 175 | if (mymtd) { | 
|  | 176 | del_mtd_partitions(mymtd); | 
|  | 177 | map_destroy(mymtd); | 
|  | 178 | iounmap((void *) db1550_map.virt); | 
|  | 179 | } | 
|  | 180 | } | 
|  | 181 |  | 
|  | 182 | module_init(db1550_mtd_init); | 
|  | 183 | module_exit(db1550_mtd_cleanup); | 
|  | 184 |  | 
|  | 185 | MODULE_AUTHOR("Embedded Edge, LLC"); | 
|  | 186 | MODULE_DESCRIPTION("Db1550 mtd map driver"); | 
|  | 187 | MODULE_LICENSE("GPL"); |