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] = kzalloc(sizeof(struct map_info), GFP_KERNEL); 136 if (map_banks[idx] == NULL) { 137 ret = -ENOMEM; 138 goto error_mem; 139 } 140 map_banks[idx]->name = kzalloc(16, GFP_KERNEL); 141 if (map_banks[idx]->name == NULL) { 142 ret = -ENOMEM; 143 goto error_mem; 144 } 145 146 sprintf(map_banks[idx]->name, "TQM834x-%d", idx); 147 map_banks[idx]->size = flash_size; 148 map_banks[idx]->bankwidth = 4; 149 150 simple_map_init(map_banks[idx]); 151 152 map_banks[idx]->virt = (void __iomem *) 153 (start_scan_addr + ((idx > 0) ? 154 (mtd_banks[idx-1] ? mtd_banks[idx-1]->size : 0) : 0)); 155 map_banks[idx]->phys = 156 flash_addr + ((idx > 0) ? 157 (mtd_banks[idx-1] ? mtd_banks[idx-1]->size : 0) : 0); 158 159 /* start to probe flash chips */ 160 mtd_banks[idx] = do_map_probe("cfi_probe", map_banks[idx]); 161 if (mtd_banks[idx]) { 162 mtd_banks[idx]->owner = THIS_MODULE; 163 mtd_size += mtd_banks[idx]->size; 164 num_banks++; 165 pr_debug("%s: bank %ld, name: %s, size: %d bytes \n", 166 __FUNCTION__, num_banks, 167 mtd_banks[idx]->name, mtd_banks[idx]->size); 168 } 169 } 170 171 /* no supported flash chips found */ 172 if (!num_banks) { 173 printk("TQM834x: No supported flash chips found!\n"); 174 ret = -ENXIO; 175 goto error_mem; 176 } 177 178#ifdef CONFIG_MTD_PARTITIONS 179 /* 180 * Select static partition definitions 181 */ 182 n = ARRAY_SIZE(tqm834x_partitions_bank1); 183 part_banks[0].mtd_part = tqm834x_partitions_bank1; 184 part_banks[0].type = "static image bank1"; 185 part_banks[0].nums = n; 186 187 /* update last partition size to cover actual remaining space */ 188 tqm834x_partitions_bank1[n - 1].size = 189 mtd_banks[0]->size - 190 tqm834x_partitions_bank1[n - 1].offset; 191 192 /* check if we have second bank? */ 193 if (num_banks == 2) { 194 n = ARRAY_SIZE(tqm834x_partitions_bank2); 195 part_banks[1].mtd_part = tqm834x_partitions_bank2; 196 part_banks[1].type = "static image bank2"; 197 part_banks[1].nums = n; 198 199 /* update last partition size to cover actual remaining space */ 200 tqm834x_partitions_bank2[n - 1].size = 201 mtd_banks[1]->size - 202 tqm834x_partitions_bank2[n - 1].offset; 203 } 204 205 for(idx = 0; idx < num_banks ; idx++) { 206#ifdef CONFIG_MTD_CMDLINE_PARTS 207 sprintf(mtdid, "%d", idx); 208 n = parse_mtd_partitions(mtd_banks[idx], 209 part_probes, 210 &part_banks[idx].mtd_part, 211 0); 212 pr_debug("%s: %d command line partitions on bank %s\n", 213 __FUNCTION__, n, mtdid); 214 if (n > 0) { 215 part_banks[idx].type = "command line"; 216 part_banks[idx].nums = n; 217 } 218#endif /* CONFIG_MTD_CMDLINE_PARTS */ 219 if (part_banks[idx].nums == 0) { 220 printk(KERN_NOTICE 221 "TQM834x flash bank %d: no partition info " 222 "available, registering whole device\n", idx); 223 add_mtd_device(mtd_banks[idx]); 224 } else { 225 printk(KERN_NOTICE 226 "TQM834x flash bank %d: Using %s partition " 227 "definition\n", idx, part_banks[idx].type); 228 add_mtd_partitions(mtd_banks[idx], 229 part_banks[idx].mtd_part, 230 part_banks[idx].nums); 231 } 232 } 233#else /* ! CONFIG_MTD_PARTITIONS */ 234 printk(KERN_NOTICE "TQM834x flash: registering %d flash banks " 235 "at once\n", num_banks); 236 237 for(idx = 0 ; idx < num_banks ; idx++) 238 add_mtd_device(mtd_banks[idx]); 239 240#endif /* CONFIG_MTD_PARTITIONS */ 241 242 return 0; 243error_mem: 244 for (idx = 0 ; idx < FLASH_BANK_MAX ; idx++) { 245 if (map_banks[idx] != NULL) { 246 if (map_banks[idx]->name != NULL) { 247 kfree(map_banks[idx]->name); 248 map_banks[idx]->name = NULL; 249 } 250 kfree(map_banks[idx]); 251 map_banks[idx] = NULL; 252 } 253 } 254 255 iounmap((void *)start_scan_addr); 256 257 return ret; 258} 259 260static void __exit cleanup_tqm834x_mtd(void) 261{ 262 unsigned int idx = 0; 263 for(idx = 0 ; idx < num_banks ; idx++) { 264 /* destroy mtd_info previously allocated */ 265 if (mtd_banks[idx]) { 266 del_mtd_partitions(mtd_banks[idx]); 267 map_destroy(mtd_banks[idx]); 268 } 269 270 /* release map_info not used anymore */ 271 kfree(map_banks[idx]->name); 272 kfree(map_banks[idx]); 273 } 274 275 if (start_scan_addr) { 276 iounmap((void *)start_scan_addr); 277 start_scan_addr = 0; 278 } 279} 280 281module_init(init_tqm834x_mtd); 282module_exit(cleanup_tqm834x_mtd); 283 284MODULE_LICENSE("GPL"); 285MODULE_AUTHOR("Wolfgang Denk <wd@denx.de>"); 286MODULE_DESCRIPTION("MTD map driver for TQM834x boards"); 287