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