Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.16-rc2 291 lines 7.8 kB view raw
1/* 2 * drivers/mtd/maps/tqm834x.c 3 * 4 * MTD mapping driver for TQM834x boards 5 * 6 * Copyright 2005 Wolfgang Denk, DENX Software Engineering, <wd@denx.de>. 7 * 8 * This file is licensed under the terms of the GNU General Public License 9 * version 2. This program is licensed "as is" without any warranty of any 10 * kind, whether express or implied. 11 * 12 */ 13 14#include <linux/config.h> 15#include <linux/init.h> 16#include <linux/module.h> 17#include <linux/types.h> 18#include <linux/kernel.h> 19#include <linux/slab.h> 20#include <asm/io.h> 21#include <asm/ppcboot.h> 22 23#include <linux/mtd/mtd.h> 24#include <linux/mtd/map.h> 25#include <linux/mtd/partitions.h> 26 27#define FLASH_BANK_MAX 2 28 29extern unsigned char __res[]; 30 31/* trivial struct to describe partition information */ 32struct mtd_part_def 33{ 34 int nums; 35 unsigned char *type; 36 struct mtd_partition* mtd_part; 37}; 38 39static struct mtd_info* mtd_banks[FLASH_BANK_MAX]; 40static struct map_info* map_banks[FLASH_BANK_MAX]; 41static struct mtd_part_def part_banks[FLASH_BANK_MAX]; 42 43static unsigned long num_banks; 44static unsigned long start_scan_addr; 45 46#ifdef CONFIG_MTD_PARTITIONS 47/* 48 * The following defines the partition layout of TQM834x boards. 49 * 50 * See include/linux/mtd/partitions.h for definition of the 51 * mtd_partition structure. 52 * 53 * Assume minimal initial size of 4 MiB per bank, will be updated 54 * later in init_tqm834x_mtd() routine. 55 */ 56 57/* Partition definition for the first flash bank which is always present. */ 58static struct mtd_partition tqm834x_partitions_bank1[] = { 59 { 60 .name = "u-boot", /* u-boot firmware */ 61 .offset = 0x00000000, 62 .size = 0x00040000, /* 256 KiB */ 63 /*mask_flags: MTD_WRITEABLE, * force read-only */ 64 }, 65 { 66 .name = "env", /* u-boot environment */ 67 .offset = 0x00040000, 68 .size = 0x00020000, /* 128 KiB */ 69 /*mask_flags: MTD_WRITEABLE, * force read-only */ 70 }, 71 { 72 .name = "kernel", /* linux kernel image */ 73 .offset = 0x00060000, 74 .size = 0x00100000, /* 1 MiB */ 75 /*mask_flags: MTD_WRITEABLE, * force read-only */ 76 }, 77 { 78 .name = "initrd", /* ramdisk image */ 79 .offset = 0x00160000, 80 .size = 0x00200000, /* 2 MiB */ 81 }, 82 { 83 .name = "user", /* user data */ 84 .offset = 0x00360000, 85 .size = 0x000a0000, /* remaining space */ 86 /* NOTE: this parttion size is re-calcated in */ 87 /* init_tqm834x_mtd() to cover actual remaining space. */ 88 }, 89}; 90 91/* Partition definition for the second flash bank which may be present on some 92 * TQM834x boards. 93 */ 94static struct mtd_partition tqm834x_partitions_bank2[] = { 95 { 96 .name = "jffs2", /* jffs2 filesystem */ 97 .offset = 0x00000000, 98 .size = 0x00400000, /* whole device */ 99 /* NOTE: this parttion size is re-calcated in */ 100 /* init_tqm834x_mtd() to cover actual device size. */ 101 }, 102}; 103 104#endif /* CONFIG_MTD_PARTITIONS */ 105 106static int __init init_tqm834x_mtd(void) 107{ 108 int idx = 0, ret = 0; 109 unsigned long flash_addr, flash_size, mtd_size = 0; 110 111 /* pointer to TQM834x board info data */ 112 bd_t *bd = (bd_t *)__res; 113#ifdef CONFIG_MTD_CMDLINE_PARTS 114 int n; 115 char mtdid[4]; 116 const char *part_probes[] = { "cmdlinepart", NULL }; 117#endif 118 119 flash_addr = bd->bi_flashstart; 120 flash_size = bd->bi_flashsize; 121 122 /* request maximum flash size address space */ 123 start_scan_addr = (unsigned long)ioremap(flash_addr, flash_size); 124 if (!start_scan_addr) { 125 printk("%s: Failed to ioremap address: 0x%lx\n", 126 __FUNCTION__, flash_addr); 127 return -EIO; 128 } 129 130 for(idx = 0 ; idx < FLASH_BANK_MAX ; idx++) { 131 if (mtd_size >= flash_size) 132 break; 133 134 pr_debug("%s: chip probing count %d\n", __FUNCTION__, idx); 135 136 map_banks[idx] = 137 (struct map_info *)kmalloc(sizeof(struct map_info), 138 GFP_KERNEL); 139 if (map_banks[idx] == NULL) { 140 ret = -ENOMEM; 141 goto error_mem; 142 } 143 memset((void *)map_banks[idx], 0, sizeof(struct map_info)); 144 map_banks[idx]->name = (char *)kmalloc(16, GFP_KERNEL); 145 if (map_banks[idx]->name == NULL) { 146 ret = -ENOMEM; 147 goto error_mem; 148 } 149 memset((void *)map_banks[idx]->name, 0, 16); 150 151 sprintf(map_banks[idx]->name, "TQM834x-%d", idx); 152 map_banks[idx]->size = flash_size; 153 map_banks[idx]->bankwidth = 4; 154 155 simple_map_init(map_banks[idx]); 156 157 map_banks[idx]->virt = (void __iomem *) 158 (start_scan_addr + ((idx > 0) ? 159 (mtd_banks[idx-1] ? mtd_banks[idx-1]->size : 0) : 0)); 160 map_banks[idx]->phys = 161 flash_addr + ((idx > 0) ? 162 (mtd_banks[idx-1] ? mtd_banks[idx-1]->size : 0) : 0); 163 164 /* start to probe flash chips */ 165 mtd_banks[idx] = do_map_probe("cfi_probe", map_banks[idx]); 166 if (mtd_banks[idx]) { 167 mtd_banks[idx]->owner = THIS_MODULE; 168 mtd_size += mtd_banks[idx]->size; 169 num_banks++; 170 pr_debug("%s: bank %ld, name: %s, size: %d bytes \n", 171 __FUNCTION__, num_banks, 172 mtd_banks[idx]->name, mtd_banks[idx]->size); 173 } 174 } 175 176 /* no supported flash chips found */ 177 if (!num_banks) { 178 printk("TQM834x: No supported flash chips found!\n"); 179 ret = -ENXIO; 180 goto error_mem; 181 } 182 183#ifdef CONFIG_MTD_PARTITIONS 184 /* 185 * Select static partition definitions 186 */ 187 n = ARRAY_SIZE(tqm834x_partitions_bank1); 188 part_banks[0].mtd_part = tqm834x_partitions_bank1; 189 part_banks[0].type = "static image bank1"; 190 part_banks[0].nums = n; 191 192 /* update last partition size to cover actual remaining space */ 193 tqm834x_partitions_bank1[n - 1].size = 194 mtd_banks[0]->size - 195 tqm834x_partitions_bank1[n - 1].offset; 196 197 /* check if we have second bank? */ 198 if (num_banks == 2) { 199 n = ARRAY_SIZE(tqm834x_partitions_bank2); 200 part_banks[1].mtd_part = tqm834x_partitions_bank2; 201 part_banks[1].type = "static image bank2"; 202 part_banks[1].nums = n; 203 204 /* update last partition size to cover actual remaining space */ 205 tqm834x_partitions_bank2[n - 1].size = 206 mtd_banks[1]->size - 207 tqm834x_partitions_bank2[n - 1].offset; 208 } 209 210 for(idx = 0; idx < num_banks ; idx++) { 211#ifdef CONFIG_MTD_CMDLINE_PARTS 212 sprintf(mtdid, "%d", idx); 213 n = parse_mtd_partitions(mtd_banks[idx], 214 part_probes, 215 &part_banks[idx].mtd_part, 216 0); 217 pr_debug("%s: %d command line partitions on bank %s\n", 218 __FUNCTION__, n, mtdid); 219 if (n > 0) { 220 part_banks[idx].type = "command line"; 221 part_banks[idx].nums = n; 222 } 223#endif /* CONFIG_MTD_CMDLINE_PARTS */ 224 if (part_banks[idx].nums == 0) { 225 printk(KERN_NOTICE 226 "TQM834x flash bank %d: no partition info " 227 "available, registering whole device\n", idx); 228 add_mtd_device(mtd_banks[idx]); 229 } else { 230 printk(KERN_NOTICE 231 "TQM834x flash bank %d: Using %s partition " 232 "definition\n", idx, part_banks[idx].type); 233 add_mtd_partitions(mtd_banks[idx], 234 part_banks[idx].mtd_part, 235 part_banks[idx].nums); 236 } 237 } 238#else /* ! CONFIG_MTD_PARTITIONS */ 239 printk(KERN_NOTICE "TQM834x flash: registering %d flash banks " 240 "at once\n", num_banks); 241 242 for(idx = 0 ; idx < num_banks ; idx++) 243 add_mtd_device(mtd_banks[idx]); 244 245#endif /* CONFIG_MTD_PARTITIONS */ 246 247 return 0; 248error_mem: 249 for (idx = 0 ; idx < FLASH_BANK_MAX ; idx++) { 250 if (map_banks[idx] != NULL) { 251 if (map_banks[idx]->name != NULL) { 252 kfree(map_banks[idx]->name); 253 map_banks[idx]->name = NULL; 254 } 255 kfree(map_banks[idx]); 256 map_banks[idx] = NULL; 257 } 258 } 259 260 iounmap((void *)start_scan_addr); 261 262 return ret; 263} 264 265static void __exit cleanup_tqm834x_mtd(void) 266{ 267 unsigned int idx = 0; 268 for(idx = 0 ; idx < num_banks ; idx++) { 269 /* destroy mtd_info previously allocated */ 270 if (mtd_banks[idx]) { 271 del_mtd_partitions(mtd_banks[idx]); 272 map_destroy(mtd_banks[idx]); 273 } 274 275 /* release map_info not used anymore */ 276 kfree(map_banks[idx]->name); 277 kfree(map_banks[idx]); 278 } 279 280 if (start_scan_addr) { 281 iounmap((void *)start_scan_addr); 282 start_scan_addr = 0; 283 } 284} 285 286module_init(init_tqm834x_mtd); 287module_exit(cleanup_tqm834x_mtd); 288 289MODULE_LICENSE("GPL"); 290MODULE_AUTHOR("Wolfgang Denk <wd@denx.de>"); 291MODULE_DESCRIPTION("MTD map driver for TQM834x boards");