diff options
| -rw-r--r-- | drivers/mtd/Kconfig | 4 | ||||
| -rw-r--r-- | drivers/mtd/ssfdc.c | 58 |
2 files changed, 34 insertions, 28 deletions
diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig index 717e90448fc6..a03e862851db 100644 --- a/drivers/mtd/Kconfig +++ b/drivers/mtd/Kconfig | |||
| @@ -101,7 +101,7 @@ config MTD_REDBOOT_PARTS_READONLY | |||
| 101 | 101 | ||
| 102 | config MTD_CMDLINE_PARTS | 102 | config MTD_CMDLINE_PARTS |
| 103 | bool "Command line partition table parsing" | 103 | bool "Command line partition table parsing" |
| 104 | depends on MTD_PARTITIONS = "y" | 104 | depends on MTD_PARTITIONS = "y" && MTD = "y" |
| 105 | ---help--- | 105 | ---help--- |
| 106 | Allow generic configuration of the MTD partition tables via the kernel | 106 | Allow generic configuration of the MTD partition tables via the kernel |
| 107 | command line. Multiple flash resources are supported for hardware where | 107 | command line. Multiple flash resources are supported for hardware where |
| @@ -264,7 +264,7 @@ config RFD_FTL | |||
| 264 | http://www.gensw.com/pages/prod/bios/rfd.htm | 264 | http://www.gensw.com/pages/prod/bios/rfd.htm |
| 265 | 265 | ||
| 266 | config SSFDC | 266 | config SSFDC |
| 267 | bool "NAND SSFDC (SmartMedia) read only translation layer" | 267 | tristate "NAND SSFDC (SmartMedia) read only translation layer" |
| 268 | depends on MTD | 268 | depends on MTD |
| 269 | default n | 269 | default n |
| 270 | help | 270 | help |
diff --git a/drivers/mtd/ssfdc.c b/drivers/mtd/ssfdc.c index ddbf015f4119..79d3bb659bfe 100644 --- a/drivers/mtd/ssfdc.c +++ b/drivers/mtd/ssfdc.c | |||
| @@ -10,7 +10,6 @@ | |||
| 10 | * published by the Free Software Foundation. | 10 | * published by the Free Software Foundation. |
| 11 | */ | 11 | */ |
| 12 | 12 | ||
| 13 | #include <linux/config.h> | ||
| 14 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
| 15 | #include <linux/module.h> | 14 | #include <linux/module.h> |
| 16 | #include <linux/init.h> | 15 | #include <linux/init.h> |
| @@ -29,7 +28,7 @@ struct ssfdcr_record { | |||
| 29 | int cis_block; /* block n. containing CIS/IDI */ | 28 | int cis_block; /* block n. containing CIS/IDI */ |
| 30 | int erase_size; /* phys_block_size */ | 29 | int erase_size; /* phys_block_size */ |
| 31 | unsigned short *logic_block_map; /* all zones (max 8192 phys blocks on | 30 | unsigned short *logic_block_map; /* all zones (max 8192 phys blocks on |
| 32 | the 128MB) */ | 31 | the 128MiB) */ |
| 33 | int map_len; /* n. phys_blocks on the card */ | 32 | int map_len; /* n. phys_blocks on the card */ |
| 34 | }; | 33 | }; |
| 35 | 34 | ||
| @@ -43,11 +42,11 @@ struct ssfdcr_record { | |||
| 43 | #define MAX_LOGIC_BLK_PER_ZONE 1000 | 42 | #define MAX_LOGIC_BLK_PER_ZONE 1000 |
| 44 | #define MAX_PHYS_BLK_PER_ZONE 1024 | 43 | #define MAX_PHYS_BLK_PER_ZONE 1024 |
| 45 | 44 | ||
| 46 | #define KB(x) ( (x) * 1024L ) | 45 | #define KiB(x) ( (x) * 1024L ) |
| 47 | #define MB(x) ( KB(x) * 1024L ) | 46 | #define MiB(x) ( KiB(x) * 1024L ) |
| 48 | 47 | ||
| 49 | /** CHS Table | 48 | /** CHS Table |
| 50 | 1MB 2MB 4MB 8MB 16MB 32MB 64MB 128MB | 49 | 1MiB 2MiB 4MiB 8MiB 16MiB 32MiB 64MiB 128MiB |
| 51 | NCylinder 125 125 250 250 500 500 500 500 | 50 | NCylinder 125 125 250 250 500 500 500 500 |
| 52 | NHead 4 4 4 4 4 8 8 16 | 51 | NHead 4 4 4 4 4 8 8 16 |
| 53 | NSector 4 8 8 16 16 16 32 32 | 52 | NSector 4 8 8 16 16 16 32 32 |
| @@ -64,14 +63,14 @@ typedef struct { | |||
| 64 | 63 | ||
| 65 | /* Must be ordered by size */ | 64 | /* Must be ordered by size */ |
| 66 | static const chs_entry_t chs_table[] = { | 65 | static const chs_entry_t chs_table[] = { |
| 67 | { MB( 1), 125, 4, 4 }, | 66 | { MiB( 1), 125, 4, 4 }, |
| 68 | { MB( 2), 125, 4, 8 }, | 67 | { MiB( 2), 125, 4, 8 }, |
| 69 | { MB( 4), 250, 4, 8 }, | 68 | { MiB( 4), 250, 4, 8 }, |
| 70 | { MB( 8), 250, 4, 16 }, | 69 | { MiB( 8), 250, 4, 16 }, |
| 71 | { MB( 16), 500, 4, 16 }, | 70 | { MiB( 16), 500, 4, 16 }, |
| 72 | { MB( 32), 500, 8, 16 }, | 71 | { MiB( 32), 500, 8, 16 }, |
| 73 | { MB( 64), 500, 8, 32 }, | 72 | { MiB( 64), 500, 8, 32 }, |
| 74 | { MB(128), 500, 16, 32 }, | 73 | { MiB(128), 500, 16, 32 }, |
| 75 | { 0 }, | 74 | { 0 }, |
| 76 | }; | 75 | }; |
| 77 | 76 | ||
| @@ -109,25 +108,30 @@ static int get_valid_cis_sector(struct mtd_info *mtd) | |||
| 109 | int ret, k, cis_sector; | 108 | int ret, k, cis_sector; |
| 110 | size_t retlen; | 109 | size_t retlen; |
| 111 | loff_t offset; | 110 | loff_t offset; |
| 112 | uint8_t sect_buf[SECTOR_SIZE]; | 111 | uint8_t *sect_buf; |
| 112 | |||
| 113 | cis_sector = -1; | ||
| 114 | |||
| 115 | sect_buf = kmalloc(SECTOR_SIZE, GFP_KERNEL); | ||
| 116 | if (!sect_buf) | ||
| 117 | goto out; | ||
| 113 | 118 | ||
| 114 | /* | 119 | /* |
| 115 | * Look for CIS/IDI sector on the first GOOD block (give up after 4 bad | 120 | * Look for CIS/IDI sector on the first GOOD block (give up after 4 bad |
| 116 | * blocks). If the first good block doesn't contain CIS number the flash | 121 | * blocks). If the first good block doesn't contain CIS number the flash |
| 117 | * is not SSFDC formatted | 122 | * is not SSFDC formatted |
| 118 | */ | 123 | */ |
| 119 | cis_sector = -1; | ||
| 120 | for (k = 0, offset = 0; k < 4; k++, offset += mtd->erasesize) { | 124 | for (k = 0, offset = 0; k < 4; k++, offset += mtd->erasesize) { |
| 121 | if (!mtd->block_isbad(mtd, offset)) { | 125 | if (!mtd->block_isbad(mtd, offset)) { |
| 122 | ret = mtd->read(mtd, offset, SECTOR_SIZE, &retlen, | 126 | ret = mtd->read(mtd, offset, SECTOR_SIZE, &retlen, |
| 123 | sect_buf); | 127 | sect_buf); |
| 124 | 128 | ||
| 125 | /* CIS pattern match on the sector buffer */ | 129 | /* CIS pattern match on the sector buffer */ |
| 126 | if ( ret < 0 || retlen != SECTOR_SIZE ) { | 130 | if (ret < 0 || retlen != SECTOR_SIZE) { |
| 127 | printk(KERN_WARNING | 131 | printk(KERN_WARNING |
| 128 | "SSFDC_RO:can't read CIS/IDI sector\n"); | 132 | "SSFDC_RO:can't read CIS/IDI sector\n"); |
| 129 | } else if ( !memcmp(sect_buf, cis_numbers, | 133 | } else if (!memcmp(sect_buf, cis_numbers, |
| 130 | sizeof(cis_numbers)) ) { | 134 | sizeof(cis_numbers))) { |
| 131 | /* Found */ | 135 | /* Found */ |
| 132 | cis_sector = (int)(offset >> SECTOR_SHIFT); | 136 | cis_sector = (int)(offset >> SECTOR_SHIFT); |
| 133 | } else { | 137 | } else { |
| @@ -140,6 +144,8 @@ static int get_valid_cis_sector(struct mtd_info *mtd) | |||
| 140 | } | 144 | } |
| 141 | } | 145 | } |
| 142 | 146 | ||
| 147 | kfree(sect_buf); | ||
| 148 | out: | ||
| 143 | return cis_sector; | 149 | return cis_sector; |
| 144 | } | 150 | } |
| 145 | 151 | ||
| @@ -227,7 +233,7 @@ static int get_logical_address(uint8_t *oob_buf) | |||
| 227 | } | 233 | } |
| 228 | } | 234 | } |
| 229 | 235 | ||
| 230 | if ( !ok ) | 236 | if (!ok) |
| 231 | block_address = -2; | 237 | block_address = -2; |
| 232 | 238 | ||
| 233 | DEBUG(MTD_DEBUG_LEVEL3, "SSFDC_RO: get_logical_address() %d\n", | 239 | DEBUG(MTD_DEBUG_LEVEL3, "SSFDC_RO: get_logical_address() %d\n", |
| @@ -245,8 +251,8 @@ static int build_logical_block_map(struct ssfdcr_record *ssfdc) | |||
| 245 | struct mtd_info *mtd = ssfdc->mbd.mtd; | 251 | struct mtd_info *mtd = ssfdc->mbd.mtd; |
| 246 | 252 | ||
| 247 | DEBUG(MTD_DEBUG_LEVEL1, "SSFDC_RO: build_block_map() nblks=%d (%luK)\n", | 253 | DEBUG(MTD_DEBUG_LEVEL1, "SSFDC_RO: build_block_map() nblks=%d (%luK)\n", |
| 248 | ssfdc->map_len, (unsigned long)ssfdc->map_len * | 254 | ssfdc->map_len, |
| 249 | ssfdc->erase_size / 1024 ); | 255 | (unsigned long)ssfdc->map_len * ssfdc->erase_size / 1024); |
| 250 | 256 | ||
| 251 | /* Scan every physical block, skip CIS block */ | 257 | /* Scan every physical block, skip CIS block */ |
| 252 | for (phys_block = ssfdc->cis_block + 1; phys_block < ssfdc->map_len; | 258 | for (phys_block = ssfdc->cis_block + 1; phys_block < ssfdc->map_len; |
| @@ -323,21 +329,21 @@ static void ssfdcr_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) | |||
| 323 | /* Set geometry */ | 329 | /* Set geometry */ |
| 324 | ssfdc->heads = 16; | 330 | ssfdc->heads = 16; |
| 325 | ssfdc->sectors = 32; | 331 | ssfdc->sectors = 32; |
| 326 | get_chs( mtd->size, NULL, &ssfdc->heads, &ssfdc->sectors); | 332 | get_chs(mtd->size, NULL, &ssfdc->heads, &ssfdc->sectors); |
| 327 | ssfdc->cylinders = (unsigned short)((mtd->size >> SECTOR_SHIFT) / | 333 | ssfdc->cylinders = (unsigned short)((mtd->size >> SECTOR_SHIFT) / |
| 328 | ((long)ssfdc->sectors * (long)ssfdc->heads)); | 334 | ((long)ssfdc->sectors * (long)ssfdc->heads)); |
| 329 | 335 | ||
| 330 | DEBUG(MTD_DEBUG_LEVEL1, "SSFDC_RO: using C:%d H:%d S:%d == %ld sects\n", | 336 | DEBUG(MTD_DEBUG_LEVEL1, "SSFDC_RO: using C:%d H:%d S:%d == %ld sects\n", |
| 331 | ssfdc->cylinders, ssfdc->heads , ssfdc->sectors, | 337 | ssfdc->cylinders, ssfdc->heads , ssfdc->sectors, |
| 332 | (long)ssfdc->cylinders * (long)ssfdc->heads * | 338 | (long)ssfdc->cylinders * (long)ssfdc->heads * |
| 333 | (long)ssfdc->sectors ); | 339 | (long)ssfdc->sectors); |
| 334 | 340 | ||
| 335 | ssfdc->mbd.size = (long)ssfdc->heads * (long)ssfdc->cylinders * | 341 | ssfdc->mbd.size = (long)ssfdc->heads * (long)ssfdc->cylinders * |
| 336 | (long)ssfdc->sectors; | 342 | (long)ssfdc->sectors; |
| 337 | 343 | ||
| 338 | /* Allocate logical block map */ | 344 | /* Allocate logical block map */ |
| 339 | ssfdc->logic_block_map = kmalloc( sizeof(ssfdc->logic_block_map[0]) * | 345 | ssfdc->logic_block_map = kmalloc(sizeof(ssfdc->logic_block_map[0]) * |
| 340 | ssfdc->map_len, GFP_KERNEL); | 346 | ssfdc->map_len, GFP_KERNEL); |
| 341 | if (!ssfdc->logic_block_map) { | 347 | if (!ssfdc->logic_block_map) { |
| 342 | printk(KERN_WARNING | 348 | printk(KERN_WARNING |
| 343 | "SSFDC_RO: out of memory for data structures\n"); | 349 | "SSFDC_RO: out of memory for data structures\n"); |
| @@ -408,7 +414,7 @@ static int ssfdcr_readsect(struct mtd_blktrans_dev *dev, | |||
| 408 | "SSFDC_RO: ssfdcr_readsect() phys_sect_no=%lu\n", | 414 | "SSFDC_RO: ssfdcr_readsect() phys_sect_no=%lu\n", |
| 409 | sect_no); | 415 | sect_no); |
| 410 | 416 | ||
| 411 | if (read_physical_sector( ssfdc->mbd.mtd, buf, sect_no ) < 0) | 417 | if (read_physical_sector(ssfdc->mbd.mtd, buf, sect_no) < 0) |
| 412 | return -EIO; | 418 | return -EIO; |
| 413 | } else { | 419 | } else { |
| 414 | memset(buf, 0xff, SECTOR_SIZE); | 420 | memset(buf, 0xff, SECTOR_SIZE); |
