Merge git://git.infradead.org/mtd-2.6

* git://git.infradead.org/mtd-2.6: (84 commits)
[JFFS2] debug.h: include <linux/sched.h> for current->pid
[MTD] OneNAND: Handle DDP chip boundary during read-while-load
[MTD] OneNAND: return ecc error code only when 2-bit ecc occurs
[MTD] OneNAND: Implement read-while-load
[MTD] OneNAND: fix onenand_wait bug in read ecc error
[MTD] OneNAND: release CPU in cycles
[MTD] OneNAND: add subpage write support
[MTD] OneNAND: fix onenand_wait bug
[JFFS2] use the ref_offset macro
[JFFS2] Reschedule in loops
[JFFS2] Fix error-path leak in summary scan
[JFFS2] add cond_resched() when garbage collecting deletion dirent
[MTD] Nuke IVR leftovers
[MTD] OneNAND: fix oob handling in recent oob patch
[MTD] Fix ssfdc blksize typo
[JFFS2] replace kmalloc+memset with kzalloc
[MTD] Fix SSFDC build for variable blocksize.
[MTD] ESB2ROM uses PCI
[MTD] of_device-based physmap driver
[MTD] Support combined RedBoot FIS directory and configuration area
...

+4402 -866
+1 -2
arch/ppc/platforms/ev64360.c
··· 358 359 ptbl_entries = 3; 360 361 - if ((ptbl = kmalloc(ptbl_entries * sizeof(struct mtd_partition), 362 GFP_KERNEL)) == NULL) { 363 364 printk(KERN_WARNING "Can't alloc MTD partition table\n"); 365 return -ENOMEM; 366 } 367 - memset(ptbl, 0, ptbl_entries * sizeof(struct mtd_partition)); 368 369 ptbl[0].name = "reserved"; 370 ptbl[0].offset = 0;
··· 358 359 ptbl_entries = 3; 360 361 + if ((ptbl = kzalloc(ptbl_entries * sizeof(struct mtd_partition), 362 GFP_KERNEL)) == NULL) { 363 364 printk(KERN_WARNING "Can't alloc MTD partition table\n"); 365 return -ENOMEM; 366 } 367 368 ptbl[0].name = "reserved"; 369 ptbl[0].offset = 0;
+13 -2
drivers/mtd/Kconfig
··· 164 memory chips, and also use ioctl() to obtain information about 165 the device, or to erase parts of it. 166 167 config MTD_BLOCK 168 tristate "Caching block device access to MTD devices" 169 depends on MTD && BLOCK 170 ---help--- 171 Although most flash chips have an erase size too large to be useful 172 as block devices, it is possible to use MTD devices which are based ··· 195 config MTD_BLOCK_RO 196 tristate "Readonly block device access to MTD devices" 197 depends on MTD_BLOCK!=y && MTD && BLOCK 198 help 199 This allows you to mount read-only file systems (such as cramfs) 200 from an MTD device, without the overhead (and danger) of the caching ··· 207 config FTL 208 tristate "FTL (Flash Translation Layer) support" 209 depends on MTD && BLOCK 210 ---help--- 211 This provides support for the original Flash Translation Layer which 212 is part of the PCMCIA specification. It uses a kind of pseudo- ··· 224 config NFTL 225 tristate "NFTL (NAND Flash Translation Layer) support" 226 depends on MTD && BLOCK 227 ---help--- 228 This provides support for the NAND Flash Translation Layer which is 229 used on M-Systems' DiskOnChip devices. It uses a kind of pseudo- ··· 248 config INFTL 249 tristate "INFTL (Inverse NAND Flash Translation Layer) support" 250 depends on MTD && BLOCK 251 ---help--- 252 This provides support for the Inverse NAND Flash Translation 253 Layer which is used on M-Systems' newer DiskOnChip devices. It ··· 266 config RFD_FTL 267 tristate "Resident Flash Disk (Flash Translation Layer) support" 268 depends on MTD && BLOCK 269 ---help--- 270 This provides support for the flash translation layer known 271 as the Resident Flash Disk (RFD), as used by the Embedded BIOS ··· 276 277 config SSFDC 278 tristate "NAND SSFDC (SmartMedia) read only translation layer" 279 - depends on MTD 280 - default n 281 help 282 This enables read only access to SmartMedia formatted NAND 283 flash. You can mount it with FAT file system.
··· 164 memory chips, and also use ioctl() to obtain information about 165 the device, or to erase parts of it. 166 167 + config MTD_BLKDEVS 168 + tristate "Common interface to block layer for MTD 'translation layers'" 169 + depends on MTD && BLOCK 170 + default n 171 + 172 config MTD_BLOCK 173 tristate "Caching block device access to MTD devices" 174 depends on MTD && BLOCK 175 + select MTD_BLKDEVS 176 ---help--- 177 Although most flash chips have an erase size too large to be useful 178 as block devices, it is possible to use MTD devices which are based ··· 189 config MTD_BLOCK_RO 190 tristate "Readonly block device access to MTD devices" 191 depends on MTD_BLOCK!=y && MTD && BLOCK 192 + select MTD_BLKDEVS 193 help 194 This allows you to mount read-only file systems (such as cramfs) 195 from an MTD device, without the overhead (and danger) of the caching ··· 200 config FTL 201 tristate "FTL (Flash Translation Layer) support" 202 depends on MTD && BLOCK 203 + select MTD_BLKDEVS 204 ---help--- 205 This provides support for the original Flash Translation Layer which 206 is part of the PCMCIA specification. It uses a kind of pseudo- ··· 216 config NFTL 217 tristate "NFTL (NAND Flash Translation Layer) support" 218 depends on MTD && BLOCK 219 + select MTD_BLKDEVS 220 ---help--- 221 This provides support for the NAND Flash Translation Layer which is 222 used on M-Systems' DiskOnChip devices. It uses a kind of pseudo- ··· 239 config INFTL 240 tristate "INFTL (Inverse NAND Flash Translation Layer) support" 241 depends on MTD && BLOCK 242 + select MTD_BLKDEVS 243 ---help--- 244 This provides support for the Inverse NAND Flash Translation 245 Layer which is used on M-Systems' newer DiskOnChip devices. It ··· 256 config RFD_FTL 257 tristate "Resident Flash Disk (Flash Translation Layer) support" 258 depends on MTD && BLOCK 259 + select MTD_BLKDEVS 260 ---help--- 261 This provides support for the flash translation layer known 262 as the Resident Flash Disk (RFD), as used by the Embedded BIOS ··· 265 266 config SSFDC 267 tristate "NAND SSFDC (SmartMedia) read only translation layer" 268 + depends on MTD && BLOCK 269 + select MTD_BLKDEVS 270 help 271 This enables read only access to SmartMedia formatted NAND 272 flash. You can mount it with FAT file system.
+8 -7
drivers/mtd/Makefile
··· 15 16 # 'Users' - code which presents functionality to userspace. 17 obj-$(CONFIG_MTD_CHAR) += mtdchar.o 18 - obj-$(CONFIG_MTD_BLOCK) += mtdblock.o mtd_blkdevs.o 19 - obj-$(CONFIG_MTD_BLOCK_RO) += mtdblock_ro.o mtd_blkdevs.o 20 - obj-$(CONFIG_FTL) += ftl.o mtd_blkdevs.o 21 - obj-$(CONFIG_NFTL) += nftl.o mtd_blkdevs.o 22 - obj-$(CONFIG_INFTL) += inftl.o mtd_blkdevs.o 23 - obj-$(CONFIG_RFD_FTL) += rfd_ftl.o mtd_blkdevs.o 24 - obj-$(CONFIG_SSFDC) += ssfdc.o mtd_blkdevs.o 25 26 nftl-objs := nftlcore.o nftlmount.o 27 inftl-objs := inftlcore.o inftlmount.o
··· 15 16 # 'Users' - code which presents functionality to userspace. 17 obj-$(CONFIG_MTD_CHAR) += mtdchar.o 18 + obj-$(CONFIG_MTD_BLKDEVS) += mtd_blkdevs.o 19 + obj-$(CONFIG_MTD_BLOCK) += mtdblock.o 20 + obj-$(CONFIG_MTD_BLOCK_RO) += mtdblock_ro.o 21 + obj-$(CONFIG_FTL) += ftl.o 22 + obj-$(CONFIG_NFTL) += nftl.o 23 + obj-$(CONFIG_INFTL) += inftl.o 24 + obj-$(CONFIG_RFD_FTL) += rfd_ftl.o 25 + obj-$(CONFIG_SSFDC) += ssfdc.o 26 27 nftl-objs := nftlcore.o nftlmount.o 28 inftl-objs := inftlcore.o inftlmount.o
+1 -2
drivers/mtd/afs.c
··· 207 if (!sz) 208 return ret; 209 210 - parts = kmalloc(sz, GFP_KERNEL); 211 if (!parts) 212 return -ENOMEM; 213 214 - memset(parts, 0, sz); 215 str = (char *)(parts + idx); 216 217 /*
··· 207 if (!sz) 208 return ret; 209 210 + parts = kzalloc(sz, GFP_KERNEL); 211 if (!parts) 212 return -ENOMEM; 213 214 str = (char *)(parts + idx); 215 216 /*
+1 -2
drivers/mtd/chips/amd_flash.c
··· 643 int reg_idx; 644 int offset; 645 646 - mtd = (struct mtd_info*)kmalloc(sizeof(*mtd), GFP_KERNEL); 647 if (!mtd) { 648 printk(KERN_WARNING 649 "%s: kmalloc failed for info structure\n", map->name); 650 return NULL; 651 } 652 - memset(mtd, 0, sizeof(*mtd)); 653 mtd->priv = map; 654 655 memset(&temp, 0, sizeof(temp));
··· 643 int reg_idx; 644 int offset; 645 646 + mtd = kzalloc(sizeof(*mtd), GFP_KERNEL); 647 if (!mtd) { 648 printk(KERN_WARNING 649 "%s: kmalloc failed for info structure\n", map->name); 650 return NULL; 651 } 652 mtd->priv = map; 653 654 memset(&temp, 0, sizeof(temp));
+3 -2
drivers/mtd/chips/cfi_cmdset_0001.c
··· 337 struct mtd_info *mtd; 338 int i; 339 340 - mtd = kmalloc(sizeof(*mtd), GFP_KERNEL); 341 if (!mtd) { 342 printk(KERN_ERR "Failed to allocate memory for MTD device\n"); 343 return NULL; 344 } 345 - memset(mtd, 0, sizeof(*mtd)); 346 mtd->priv = map; 347 mtd->type = MTD_NORFLASH; 348 ··· 2223 case FL_CFI_QUERY: 2224 case FL_JEDEC_QUERY: 2225 if (chip->oldstate == FL_READY) { 2226 chip->oldstate = chip->state; 2227 chip->state = FL_PM_SUSPENDED; 2228 /* No need to wake_up() on this state change -
··· 337 struct mtd_info *mtd; 338 int i; 339 340 + mtd = kzalloc(sizeof(*mtd), GFP_KERNEL); 341 if (!mtd) { 342 printk(KERN_ERR "Failed to allocate memory for MTD device\n"); 343 return NULL; 344 } 345 mtd->priv = map; 346 mtd->type = MTD_NORFLASH; 347 ··· 2224 case FL_CFI_QUERY: 2225 case FL_JEDEC_QUERY: 2226 if (chip->oldstate == FL_READY) { 2227 + /* place the chip in a known state before suspend */ 2228 + map_write(map, CMD(0xFF), cfi->chips[i].start); 2229 chip->oldstate = chip->state; 2230 chip->state = FL_PM_SUSPENDED; 2231 /* No need to wake_up() on this state change -
+7 -4
drivers/mtd/chips/cfi_cmdset_0002.c
··· 48 #define MANUFACTURER_ATMEL 0x001F 49 #define MANUFACTURER_SST 0x00BF 50 #define SST49LF004B 0x0060 51 #define SST49LF008A 0x005a 52 #define AT49BV6416 0x00d6 53 ··· 234 }; 235 static struct cfi_fixup jedec_fixup_table[] = { 236 { MANUFACTURER_SST, SST49LF004B, fixup_use_fwh_lock, NULL, }, 237 { MANUFACTURER_SST, SST49LF008A, fixup_use_fwh_lock, NULL, }, 238 { 0, 0, NULL, NULL } 239 }; ··· 257 struct mtd_info *mtd; 258 int i; 259 260 - mtd = kmalloc(sizeof(*mtd), GFP_KERNEL); 261 if (!mtd) { 262 printk(KERN_WARNING "Failed to allocate memory for MTD device\n"); 263 return NULL; 264 } 265 - memset(mtd, 0, sizeof(*mtd)); 266 mtd->priv = map; 267 mtd->type = MTD_NORFLASH; 268 ··· 520 if (mode == FL_WRITING) /* FIXME: Erase-suspend-program appears broken. */ 521 goto sleep; 522 523 - if (!(mode == FL_READY || mode == FL_POINT 524 || !cfip 525 || (mode == FL_WRITING && (cfip->EraseSuspend & 0x2)) 526 - || (mode == FL_WRITING && (cfip->EraseSuspend & 0x1)))) 527 goto sleep; 528 529 /* We could check to see if we're trying to access the sector
··· 48 #define MANUFACTURER_ATMEL 0x001F 49 #define MANUFACTURER_SST 0x00BF 50 #define SST49LF004B 0x0060 51 + #define SST49LF040B 0x0050 52 #define SST49LF008A 0x005a 53 #define AT49BV6416 0x00d6 54 ··· 233 }; 234 static struct cfi_fixup jedec_fixup_table[] = { 235 { MANUFACTURER_SST, SST49LF004B, fixup_use_fwh_lock, NULL, }, 236 + { MANUFACTURER_SST, SST49LF040B, fixup_use_fwh_lock, NULL, }, 237 { MANUFACTURER_SST, SST49LF008A, fixup_use_fwh_lock, NULL, }, 238 { 0, 0, NULL, NULL } 239 }; ··· 255 struct mtd_info *mtd; 256 int i; 257 258 + mtd = kzalloc(sizeof(*mtd), GFP_KERNEL); 259 if (!mtd) { 260 printk(KERN_WARNING "Failed to allocate memory for MTD device\n"); 261 return NULL; 262 } 263 mtd->priv = map; 264 mtd->type = MTD_NORFLASH; 265 ··· 519 if (mode == FL_WRITING) /* FIXME: Erase-suspend-program appears broken. */ 520 goto sleep; 521 522 + if (!( mode == FL_READY 523 + || mode == FL_POINT 524 || !cfip 525 || (mode == FL_WRITING && (cfip->EraseSuspend & 0x2)) 526 + || (mode == FL_WRITING && (cfip->EraseSuspend & 0x1) 527 + ))) 528 goto sleep; 529 530 /* We could check to see if we're trying to access the sector
+1 -2
drivers/mtd/chips/cfi_cmdset_0020.c
··· 172 int i,j; 173 unsigned long devsize = (1<<cfi->cfiq->DevSize) * cfi->interleave; 174 175 - mtd = kmalloc(sizeof(*mtd), GFP_KERNEL); 176 //printk(KERN_DEBUG "number of CFI chips: %d\n", cfi->numchips); 177 178 if (!mtd) { ··· 181 return NULL; 182 } 183 184 - memset(mtd, 0, sizeof(*mtd)); 185 mtd->priv = map; 186 mtd->type = MTD_NORFLASH; 187 mtd->size = devsize * cfi->numchips;
··· 172 int i,j; 173 unsigned long devsize = (1<<cfi->cfiq->DevSize) * cfi->interleave; 174 175 + mtd = kzalloc(sizeof(*mtd), GFP_KERNEL); 176 //printk(KERN_DEBUG "number of CFI chips: %d\n", cfi->numchips); 177 178 if (!mtd) { ··· 181 return NULL; 182 } 183 184 mtd->priv = map; 185 mtd->type = MTD_NORFLASH; 186 mtd->size = devsize * cfi->numchips;
+2 -3
drivers/mtd/chips/gen_probe.c
··· 40 if (mtd) { 41 if (mtd->size > map->size) { 42 printk(KERN_WARNING "Reducing visibility of %ldKiB chip to %ldKiB\n", 43 - (unsigned long)mtd->size >> 10, 44 (unsigned long)map->size >> 10); 45 mtd->size = map->size; 46 } ··· 113 } 114 115 mapsize = (max_chips + BITS_PER_LONG-1) / BITS_PER_LONG; 116 - chip_map = kmalloc(mapsize, GFP_KERNEL); 117 if (!chip_map) { 118 printk(KERN_WARNING "%s: kmalloc failed for CFI chip map\n", map->name); 119 kfree(cfi.cfiq); 120 return NULL; 121 } 122 - memset (chip_map, 0, mapsize); 123 124 set_bit(0, chip_map); /* Mark first chip valid */ 125
··· 40 if (mtd) { 41 if (mtd->size > map->size) { 42 printk(KERN_WARNING "Reducing visibility of %ldKiB chip to %ldKiB\n", 43 + (unsigned long)mtd->size >> 10, 44 (unsigned long)map->size >> 10); 45 mtd->size = map->size; 46 } ··· 113 } 114 115 mapsize = (max_chips + BITS_PER_LONG-1) / BITS_PER_LONG; 116 + chip_map = kzalloc(mapsize, GFP_KERNEL); 117 if (!chip_map) { 118 printk(KERN_WARNING "%s: kmalloc failed for CFI chip map\n", map->name); 119 kfree(cfi.cfiq); 120 return NULL; 121 } 122 123 set_bit(0, chip_map); /* Mark first chip valid */ 124
+1 -2
drivers/mtd/chips/jedec.c
··· 116 char Part[200]; 117 memset(&priv,0,sizeof(priv)); 118 119 - MTD = kmalloc(sizeof(struct mtd_info) + sizeof(struct jedec_private), GFP_KERNEL); 120 if (!MTD) 121 return NULL; 122 123 - memset(MTD, 0, sizeof(struct mtd_info) + sizeof(struct jedec_private)); 124 priv = (struct jedec_private *)&MTD[1]; 125 126 my_bank_size = map->size;
··· 116 char Part[200]; 117 memset(&priv,0,sizeof(priv)); 118 119 + MTD = kzalloc(sizeof(struct mtd_info) + sizeof(struct jedec_private), GFP_KERNEL); 120 if (!MTD) 121 return NULL; 122 123 priv = (struct jedec_private *)&MTD[1]; 124 125 my_bank_size = map->size;
+16 -1
drivers/mtd/chips/jedec_probe.c
··· 154 #define SST39SF010A 0x00B5 155 #define SST39SF020A 0x00B6 156 #define SST49LF004B 0x0060 157 #define SST49LF008A 0x005a 158 #define SST49LF030A 0x001C 159 #define SST49LF040A 0x0051 ··· 1402 } 1403 }, { 1404 .mfr_id = MANUFACTURER_SST, 1405 .dev_id = SST49LF004B, 1406 .name = "SST 49LF004B", 1407 .uaddr = { ··· 1889 1890 1891 /* 1892 - * There is a BIG problem properly ID'ing the JEDEC devic and guaranteeing 1893 * the mapped address, unlock addresses, and proper chip ID. This function 1894 * attempts to minimize errors. It is doubtfull that this probe will ever 1895 * be perfect - consequently there should be some module parameters that
··· 154 #define SST39SF010A 0x00B5 155 #define SST39SF020A 0x00B6 156 #define SST49LF004B 0x0060 157 + #define SST49LF040B 0x0050 158 #define SST49LF008A 0x005a 159 #define SST49LF030A 0x001C 160 #define SST49LF040A 0x0051 ··· 1401 } 1402 }, { 1403 .mfr_id = MANUFACTURER_SST, 1404 + .dev_id = SST49LF040B, 1405 + .name = "SST 49LF040B", 1406 + .uaddr = { 1407 + [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */ 1408 + }, 1409 + .DevSize = SIZE_512KiB, 1410 + .CmdSet = P_ID_AMD_STD, 1411 + .NumEraseRegions= 1, 1412 + .regions = { 1413 + ERASEINFO(0x01000,128), 1414 + } 1415 + }, { 1416 + 1417 + .mfr_id = MANUFACTURER_SST, 1418 .dev_id = SST49LF004B, 1419 .name = "SST 49LF004B", 1420 .uaddr = { ··· 1874 1875 1876 /* 1877 + * There is a BIG problem properly ID'ing the JEDEC device and guaranteeing 1878 * the mapped address, unlock addresses, and proper chip ID. This function 1879 * attempts to minimize errors. It is doubtfull that this probe will ever 1880 * be perfect - consequently there should be some module parameters that
+1 -3
drivers/mtd/chips/map_absent.c
··· 47 { 48 struct mtd_info *mtd; 49 50 - mtd = kmalloc(sizeof(*mtd), GFP_KERNEL); 51 if (!mtd) { 52 return NULL; 53 } 54 - 55 - memset(mtd, 0, sizeof(*mtd)); 56 57 map->fldrv = &map_absent_chipdrv; 58 mtd->priv = map;
··· 47 { 48 struct mtd_info *mtd; 49 50 + mtd = kzalloc(sizeof(*mtd), GFP_KERNEL); 51 if (!mtd) { 52 return NULL; 53 } 54 55 map->fldrv = &map_absent_chipdrv; 56 mtd->priv = map;
+1 -3
drivers/mtd/chips/map_ram.c
··· 55 #endif 56 /* OK. It seems to be RAM. */ 57 58 - mtd = kmalloc(sizeof(*mtd), GFP_KERNEL); 59 if (!mtd) 60 return NULL; 61 - 62 - memset(mtd, 0, sizeof(*mtd)); 63 64 map->fldrv = &mapram_chipdrv; 65 mtd->priv = map;
··· 55 #endif 56 /* OK. It seems to be RAM. */ 57 58 + mtd = kzalloc(sizeof(*mtd), GFP_KERNEL); 59 if (!mtd) 60 return NULL; 61 62 map->fldrv = &mapram_chipdrv; 63 mtd->priv = map;
+1 -3
drivers/mtd/chips/map_rom.c
··· 31 { 32 struct mtd_info *mtd; 33 34 - mtd = kmalloc(sizeof(*mtd), GFP_KERNEL); 35 if (!mtd) 36 return NULL; 37 - 38 - memset(mtd, 0, sizeof(*mtd)); 39 40 map->fldrv = &maprom_chipdrv; 41 mtd->priv = map;
··· 31 { 32 struct mtd_info *mtd; 33 34 + mtd = kzalloc(sizeof(*mtd), GFP_KERNEL); 35 if (!mtd) 36 return NULL; 37 38 map->fldrv = &maprom_chipdrv; 39 mtd->priv = map;
+2 -5
drivers/mtd/chips/sharp.c
··· 112 struct sharp_info *sharp = NULL; 113 int width; 114 115 - mtd = kmalloc(sizeof(*mtd), GFP_KERNEL); 116 if(!mtd) 117 return NULL; 118 119 - sharp = kmalloc(sizeof(*sharp), GFP_KERNEL); 120 if(!sharp) { 121 kfree(mtd); 122 return NULL; 123 } 124 - 125 - memset(mtd, 0, sizeof(*mtd)); 126 127 width = sharp_probe_map(map,mtd); 128 if(!width){ ··· 141 mtd->writesize = 1; 142 mtd->name = map->name; 143 144 - memset(sharp, 0, sizeof(*sharp)); 145 sharp->chipshift = 23; 146 sharp->numchips = 1; 147 sharp->chips[0].start = 0;
··· 112 struct sharp_info *sharp = NULL; 113 int width; 114 115 + mtd = kzalloc(sizeof(*mtd), GFP_KERNEL); 116 if(!mtd) 117 return NULL; 118 119 + sharp = kzalloc(sizeof(*sharp), GFP_KERNEL); 120 if(!sharp) { 121 kfree(mtd); 122 return NULL; 123 } 124 125 width = sharp_probe_map(map,mtd); 126 if(!width){ ··· 143 mtd->writesize = 1; 144 mtd->name = map->name; 145 146 sharp->chipshift = 23; 147 sharp->numchips = 1; 148 sharp->chips[0].start = 0;
+2 -3
drivers/mtd/cmdlinepart.c
··· 163 *num_parts = this_part + 1; 164 alloc_size = *num_parts * sizeof(struct mtd_partition) + 165 extra_mem_size; 166 - parts = kmalloc(alloc_size, GFP_KERNEL); 167 if (!parts) 168 { 169 printk(KERN_ERR ERRP "out of memory\n"); 170 return NULL; 171 } 172 - memset(parts, 0, alloc_size); 173 extra_mem = (unsigned char *)(parts + *num_parts); 174 } 175 /* enter this partition (offset will be calculated later if it is zero at this point) */ ··· 345 * 346 * This function needs to be visible for bootloaders. 347 */ 348 - int mtdpart_setup(char *s) 349 { 350 cmdline = s; 351 return 1;
··· 163 *num_parts = this_part + 1; 164 alloc_size = *num_parts * sizeof(struct mtd_partition) + 165 extra_mem_size; 166 + parts = kzalloc(alloc_size, GFP_KERNEL); 167 if (!parts) 168 { 169 printk(KERN_ERR ERRP "out of memory\n"); 170 return NULL; 171 } 172 extra_mem = (unsigned char *)(parts + *num_parts); 173 } 174 /* enter this partition (offset will be calculated later if it is zero at this point) */ ··· 346 * 347 * This function needs to be visible for bootloaders. 348 */ 349 + static int mtdpart_setup(char *s) 350 { 351 cmdline = s; 352 return 1;
+1 -2
drivers/mtd/devices/block2mtd.c
··· 295 if (!devname) 296 return NULL; 297 298 - dev = kmalloc(sizeof(struct block2mtd_dev), GFP_KERNEL); 299 if (!dev) 300 return NULL; 301 - memset(dev, 0, sizeof(*dev)); 302 303 /* Get a handle on the device */ 304 bdev = open_bdev_excl(devname, O_RDWR, NULL);
··· 295 if (!devname) 296 return NULL; 297 298 + dev = kzalloc(sizeof(struct block2mtd_dev), GFP_KERNEL); 299 if (!dev) 300 return NULL; 301 302 /* Get a handle on the device */ 303 bdev = open_bdev_excl(devname, O_RDWR, NULL);
+6 -12
drivers/mtd/devices/ms02-nv.c
··· 131 int ret = -ENODEV; 132 133 /* The module decodes 8MiB of address space. */ 134 - mod_res = kmalloc(sizeof(*mod_res), GFP_KERNEL); 135 if (!mod_res) 136 return -ENOMEM; 137 138 - memset(mod_res, 0, sizeof(*mod_res)); 139 mod_res->name = ms02nv_name; 140 mod_res->start = addr; 141 mod_res->end = addr + MS02NV_SLOT_SIZE - 1; ··· 152 } 153 154 ret = -ENOMEM; 155 - mtd = kmalloc(sizeof(*mtd), GFP_KERNEL); 156 if (!mtd) 157 goto err_out_mod_res_rel; 158 - memset(mtd, 0, sizeof(*mtd)); 159 - mp = kmalloc(sizeof(*mp), GFP_KERNEL); 160 if (!mp) 161 goto err_out_mtd; 162 - memset(mp, 0, sizeof(*mp)); 163 164 mtd->priv = mp; 165 mp->resource.module = mod_res; 166 167 /* Firmware's diagnostic NVRAM area. */ 168 - diag_res = kmalloc(sizeof(*diag_res), GFP_KERNEL); 169 if (!diag_res) 170 goto err_out_mp; 171 172 - memset(diag_res, 0, sizeof(*diag_res)); 173 diag_res->name = ms02nv_res_diag_ram; 174 diag_res->start = addr; 175 diag_res->end = addr + MS02NV_RAM - 1; ··· 176 mp->resource.diag_ram = diag_res; 177 178 /* User-available general-purpose NVRAM area. */ 179 - user_res = kmalloc(sizeof(*user_res), GFP_KERNEL); 180 if (!user_res) 181 goto err_out_diag_res; 182 183 - memset(user_res, 0, sizeof(*user_res)); 184 user_res->name = ms02nv_res_user_ram; 185 user_res->start = addr + MS02NV_RAM; 186 user_res->end = addr + size - 1; ··· 189 mp->resource.user_ram = user_res; 190 191 /* Control and status register. */ 192 - csr_res = kmalloc(sizeof(*csr_res), GFP_KERNEL); 193 if (!csr_res) 194 goto err_out_user_res; 195 196 - memset(csr_res, 0, sizeof(*csr_res)); 197 csr_res->name = ms02nv_res_csr; 198 csr_res->start = addr + MS02NV_CSR; 199 csr_res->end = addr + MS02NV_CSR + 3;
··· 131 int ret = -ENODEV; 132 133 /* The module decodes 8MiB of address space. */ 134 + mod_res = kzalloc(sizeof(*mod_res), GFP_KERNEL); 135 if (!mod_res) 136 return -ENOMEM; 137 138 mod_res->name = ms02nv_name; 139 mod_res->start = addr; 140 mod_res->end = addr + MS02NV_SLOT_SIZE - 1; ··· 153 } 154 155 ret = -ENOMEM; 156 + mtd = kzalloc(sizeof(*mtd), GFP_KERNEL); 157 if (!mtd) 158 goto err_out_mod_res_rel; 159 + mp = kzalloc(sizeof(*mp), GFP_KERNEL); 160 if (!mp) 161 goto err_out_mtd; 162 163 mtd->priv = mp; 164 mp->resource.module = mod_res; 165 166 /* Firmware's diagnostic NVRAM area. */ 167 + diag_res = kzalloc(sizeof(*diag_res), GFP_KERNEL); 168 if (!diag_res) 169 goto err_out_mp; 170 171 diag_res->name = ms02nv_res_diag_ram; 172 diag_res->start = addr; 173 diag_res->end = addr + MS02NV_RAM - 1; ··· 180 mp->resource.diag_ram = diag_res; 181 182 /* User-available general-purpose NVRAM area. */ 183 + user_res = kzalloc(sizeof(*user_res), GFP_KERNEL); 184 if (!user_res) 185 goto err_out_diag_res; 186 187 user_res->name = ms02nv_res_user_ram; 188 user_res->start = addr + MS02NV_RAM; 189 user_res->end = addr + size - 1; ··· 194 mp->resource.user_ram = user_res; 195 196 /* Control and status register. */ 197 + csr_res = kzalloc(sizeof(*csr_res), GFP_KERNEL); 198 if (!csr_res) 199 goto err_out_user_res; 200 201 csr_res->name = ms02nv_res_csr; 202 csr_res->start = addr + MS02NV_CSR; 203 csr_res->end = addr + MS02NV_CSR + 3;
+1 -1
drivers/mtd/devices/mtd_dataflash.c
··· 480 device->writesize = pagesize; 481 device->owner = THIS_MODULE; 482 device->type = MTD_DATAFLASH; 483 - device->flags = MTD_CAP_NORFLASH; 484 device->erase = dataflash_erase; 485 device->read = dataflash_read; 486 device->write = dataflash_write;
··· 480 device->writesize = pagesize; 481 device->owner = THIS_MODULE; 482 device->type = MTD_DATAFLASH; 483 + device->flags = MTD_WRITEABLE; 484 device->erase = dataflash_erase; 485 device->read = dataflash_read; 486 device->write = dataflash_write;
+1 -3
drivers/mtd/devices/phram.c
··· 126 struct phram_mtd_list *new; 127 int ret = -ENOMEM; 128 129 - new = kmalloc(sizeof(*new), GFP_KERNEL); 130 if (!new) 131 goto out0; 132 - 133 - memset(new, 0, sizeof(*new)); 134 135 ret = -EIO; 136 new->mtd.priv = ioremap(start, len);
··· 126 struct phram_mtd_list *new; 127 int ret = -ENOMEM; 128 129 + new = kzalloc(sizeof(*new), GFP_KERNEL); 130 if (!new) 131 goto out0; 132 133 ret = -EIO; 134 new->mtd.priv = ioremap(start, len);
+2 -5
drivers/mtd/devices/slram.c
··· 168 E("slram: Cannot allocate new MTD device.\n"); 169 return(-ENOMEM); 170 } 171 - (*curmtd)->mtdinfo = kmalloc(sizeof(struct mtd_info), GFP_KERNEL); 172 (*curmtd)->next = NULL; 173 174 if ((*curmtd)->mtdinfo) { 175 - memset((char *)(*curmtd)->mtdinfo, 0, sizeof(struct mtd_info)); 176 (*curmtd)->mtdinfo->priv = 177 - kmalloc(sizeof(slram_priv_t), GFP_KERNEL); 178 179 if (!(*curmtd)->mtdinfo->priv) { 180 kfree((*curmtd)->mtdinfo); 181 (*curmtd)->mtdinfo = NULL; 182 - } else { 183 - memset((*curmtd)->mtdinfo->priv,0,sizeof(slram_priv_t)); 184 } 185 } 186
··· 168 E("slram: Cannot allocate new MTD device.\n"); 169 return(-ENOMEM); 170 } 171 + (*curmtd)->mtdinfo = kzalloc(sizeof(struct mtd_info), GFP_KERNEL); 172 (*curmtd)->next = NULL; 173 174 if ((*curmtd)->mtdinfo) { 175 (*curmtd)->mtdinfo->priv = 176 + kzalloc(sizeof(slram_priv_t), GFP_KERNEL); 177 178 if (!(*curmtd)->mtdinfo->priv) { 179 kfree((*curmtd)->mtdinfo); 180 (*curmtd)->mtdinfo = NULL; 181 } 182 } 183
+3 -4
drivers/mtd/ftl.c
··· 1033 { 1034 partition_t *partition; 1035 1036 - partition = kmalloc(sizeof(partition_t), GFP_KERNEL); 1037 1038 if (!partition) { 1039 printk(KERN_WARNING "No memory to scan for FTL on %s\n", 1040 mtd->name); 1041 return; 1042 } 1043 - 1044 - memset(partition, 0, sizeof(partition_t)); 1045 1046 partition->mbd.mtd = mtd; 1047 ··· 1052 le32_to_cpu(partition->header.FormattedSize) >> 10); 1053 #endif 1054 partition->mbd.size = le32_to_cpu(partition->header.FormattedSize) >> 9; 1055 - partition->mbd.blksize = SECTOR_SIZE; 1056 partition->mbd.tr = tr; 1057 partition->mbd.devnum = -1; 1058 if (!add_mtd_blktrans_dev((void *)partition)) ··· 1074 .name = "ftl", 1075 .major = FTL_MAJOR, 1076 .part_bits = PART_BITS, 1077 .readsect = ftl_readsect, 1078 .writesect = ftl_writesect, 1079 .getgeo = ftl_getgeo,
··· 1033 { 1034 partition_t *partition; 1035 1036 + partition = kzalloc(sizeof(partition_t), GFP_KERNEL); 1037 1038 if (!partition) { 1039 printk(KERN_WARNING "No memory to scan for FTL on %s\n", 1040 mtd->name); 1041 return; 1042 } 1043 1044 partition->mbd.mtd = mtd; 1045 ··· 1054 le32_to_cpu(partition->header.FormattedSize) >> 10); 1055 #endif 1056 partition->mbd.size = le32_to_cpu(partition->header.FormattedSize) >> 9; 1057 + 1058 partition->mbd.tr = tr; 1059 partition->mbd.devnum = -1; 1060 if (!add_mtd_blktrans_dev((void *)partition)) ··· 1076 .name = "ftl", 1077 .major = FTL_MAJOR, 1078 .part_bits = PART_BITS, 1079 + .blksize = SECTOR_SIZE, 1080 .readsect = ftl_readsect, 1081 .writesect = ftl_writesect, 1082 .getgeo = ftl_getgeo,
+5 -7
drivers/mtd/inftlcore.c
··· 67 68 DEBUG(MTD_DEBUG_LEVEL3, "INFTL: add_mtd for %s\n", mtd->name); 69 70 - inftl = kmalloc(sizeof(*inftl), GFP_KERNEL); 71 72 if (!inftl) { 73 printk(KERN_WARNING "INFTL: Out of memory for data structures\n"); 74 return; 75 } 76 - memset(inftl, 0, sizeof(*inftl)); 77 78 inftl->mbd.mtd = mtd; 79 inftl->mbd.devnum = -1; 80 - inftl->mbd.blksize = 512; 81 inftl->mbd.tr = tr; 82 83 if (INFTL_mount(inftl) < 0) { ··· 162 ops.ooblen = len; 163 ops.oobbuf = buf; 164 ops.datbuf = NULL; 165 - ops.len = len; 166 167 res = mtd->read_oob(mtd, offs & ~(mtd->writesize - 1), &ops); 168 - *retlen = ops.retlen; 169 return res; 170 } 171 ··· 182 ops.ooblen = len; 183 ops.oobbuf = buf; 184 ops.datbuf = NULL; 185 - ops.len = len; 186 187 res = mtd->write_oob(mtd, offs & ~(mtd->writesize - 1), &ops); 188 - *retlen = ops.retlen; 189 return res; 190 } 191 ··· 942 .name = "inftl", 943 .major = INFTL_MAJOR, 944 .part_bits = INFTL_PARTN_BITS, 945 .getgeo = inftl_getgeo, 946 .readsect = inftl_readblock, 947 .writesect = inftl_writeblock,
··· 67 68 DEBUG(MTD_DEBUG_LEVEL3, "INFTL: add_mtd for %s\n", mtd->name); 69 70 + inftl = kzalloc(sizeof(*inftl), GFP_KERNEL); 71 72 if (!inftl) { 73 printk(KERN_WARNING "INFTL: Out of memory for data structures\n"); 74 return; 75 } 76 77 inftl->mbd.mtd = mtd; 78 inftl->mbd.devnum = -1; 79 + 80 inftl->mbd.tr = tr; 81 82 if (INFTL_mount(inftl) < 0) { ··· 163 ops.ooblen = len; 164 ops.oobbuf = buf; 165 ops.datbuf = NULL; 166 167 res = mtd->read_oob(mtd, offs & ~(mtd->writesize - 1), &ops); 168 + *retlen = ops.oobretlen; 169 return res; 170 } 171 ··· 184 ops.ooblen = len; 185 ops.oobbuf = buf; 186 ops.datbuf = NULL; 187 188 res = mtd->write_oob(mtd, offs & ~(mtd->writesize - 1), &ops); 189 + *retlen = ops.oobretlen; 190 return res; 191 } 192 ··· 945 .name = "inftl", 946 .major = INFTL_MAJOR, 947 .part_bits = INFTL_PARTN_BITS, 948 + .blksize = 512, 949 .getgeo = inftl_getgeo, 950 .readsect = inftl_readblock, 951 .writesect = inftl_writeblock,
+27 -44
drivers/mtd/maps/Kconfig
··· 60 Ignore this option if you use run-time physmap configuration 61 (i.e., run-time calling physmap_configure()). 62 63 config MTD_SUN_UFLASH 64 tristate "Sun Microsystems userflash support" 65 depends on SPARC && MTD_CFI ··· 189 depends on X86 && MTD_JEDECPROBE 190 help 191 Support for treating the BIOS flash chip on ICHX motherboards 192 as an MTD device - with this you can reprogram your BIOS. 193 194 BE VERY CAREFUL. ··· 381 This enables access routines for the flash chips on the 382 TQ Components TQM834x boards. If you have one of these boards 383 and would like to use the flash chips on it, say 'Y'. 384 - 385 - config MTD_CSTM_MIPS_IXX 386 - tristate "Flash chip mapping on ITE QED-4N-S01B, Globespan IVR or custom board" 387 - depends on MIPS && MTD_CFI && MTD_JEDECPROBE && MTD_PARTITIONS 388 - help 389 - This provides a mapping driver for the Integrated Technology 390 - Express, Inc (ITE) QED-4N-S01B eval board and the Globespan IVR 391 - Reference Board. It provides the necessary addressing, length, 392 - buswidth, vpp code and addition setup of the flash device for 393 - these boards. In addition, this mapping driver can be used for 394 - other boards via setting of the CONFIG_MTD_CSTM_MIPS_IXX_START/ 395 - LEN/BUSWIDTH parameters. This mapping will provide one mtd device 396 - using one partition. The start address can be offset from the 397 - beginning of flash and the len can be less than the total flash 398 - device size to allow a window into the flash. Both CFI and JEDEC 399 - probes are called. 400 - 401 - config MTD_CSTM_MIPS_IXX_START 402 - hex "Physical start address of flash mapping" 403 - depends on MTD_CSTM_MIPS_IXX 404 - default "0x8000000" 405 - help 406 - This is the physical memory location that the MTD driver will 407 - use for the flash chips on your particular target board. 408 - Refer to the memory map which should hopefully be in the 409 - documentation for your board. 410 - 411 - config MTD_CSTM_MIPS_IXX_LEN 412 - hex "Physical length of flash mapping" 413 - depends on MTD_CSTM_MIPS_IXX 414 - default "0x4000000" 415 - help 416 - This is the total length that the MTD driver will use for the 417 - flash chips on your particular board. Refer to the memory 418 - map which should hopefully be in the documentation for your 419 - board. 420 - 421 - config MTD_CSTM_MIPS_IXX_BUSWIDTH 422 - int "Bus width in octets" 423 - depends on MTD_CSTM_MIPS_IXX 424 - default "2" 425 - help 426 - This is the total bus width of the mapping of the flash chips 427 - on your particular board. 428 429 config MTD_OCELOT 430 tristate "Momenco Ocelot boot flash device"
··· 60 Ignore this option if you use run-time physmap configuration 61 (i.e., run-time calling physmap_configure()). 62 63 + config MTD_PHYSMAP_OF 64 + tristate "Flash device in physical memory map based on OF descirption" 65 + depends on PPC_OF && (MTD_CFI || MTD_JEDECPROBE || MTD_ROM) 66 + help 67 + This provides a 'mapping' driver which allows the NOR Flash and 68 + ROM driver code to communicate with chips which are mapped 69 + physically into the CPU's memory. The mapping description here is 70 + taken from OF device tree. 71 + 72 config MTD_SUN_UFLASH 73 tristate "Sun Microsystems userflash support" 74 depends on SPARC && MTD_CFI ··· 180 depends on X86 && MTD_JEDECPROBE 181 help 182 Support for treating the BIOS flash chip on ICHX motherboards 183 + as an MTD device - with this you can reprogram your BIOS. 184 + 185 + BE VERY CAREFUL. 186 + 187 + config MTD_ESB2ROM 188 + tristate "BIOS flash chip on Intel ESB Controller Hub 2" 189 + depends on X86 && MTD_JEDECPROBE && PCI 190 + help 191 + Support for treating the BIOS flash chip on ESB2 motherboards 192 + as an MTD device - with this you can reprogram your BIOS. 193 + 194 + BE VERY CAREFUL. 195 + 196 + config MTD_CK804XROM 197 + tristate "BIOS flash chip on Nvidia CK804" 198 + depends on X86 && MTD_JEDECPROBE 199 + help 200 + Support for treating the BIOS flash chip on nvidia motherboards 201 as an MTD device - with this you can reprogram your BIOS. 202 203 BE VERY CAREFUL. ··· 354 This enables access routines for the flash chips on the 355 TQ Components TQM834x boards. If you have one of these boards 356 and would like to use the flash chips on it, say 'Y'. 357 358 config MTD_OCELOT 359 tristate "Momenco Ocelot boot flash device"
+3 -1
drivers/mtd/maps/Makefile
··· 12 obj-$(CONFIG_MTD_ARM_INTEGRATOR)+= integrator-flash.o 13 obj-$(CONFIG_MTD_BAST) += bast-flash.o 14 obj-$(CONFIG_MTD_CFI_FLAGADM) += cfi_flagadm.o 15 - obj-$(CONFIG_MTD_CSTM_MIPS_IXX) += cstm_mips_ixx.o 16 obj-$(CONFIG_MTD_DC21285) += dc21285.o 17 obj-$(CONFIG_MTD_DILNETPC) += dilnetpc.o 18 obj-$(CONFIG_MTD_L440GX) += l440gx.o 19 obj-$(CONFIG_MTD_AMD76XROM) += amd76xrom.o 20 obj-$(CONFIG_MTD_ICHXROM) += ichxrom.o 21 obj-$(CONFIG_MTD_TSUNAMI) += tsunami_flash.o 22 obj-$(CONFIG_MTD_LUBBOCK) += lubbock-flash.o 23 obj-$(CONFIG_MTD_MAINSTONE) += mainstone-flash.o ··· 26 obj-$(CONFIG_MTD_CEIVA) += ceiva.o 27 obj-$(CONFIG_MTD_OCTAGON) += octagon-5066.o 28 obj-$(CONFIG_MTD_PHYSMAP) += physmap.o 29 obj-$(CONFIG_MTD_PNC2000) += pnc2000.o 30 obj-$(CONFIG_MTD_PCMCIA) += pcmciamtd.o 31 obj-$(CONFIG_MTD_RPXLITE) += rpxlite.o
··· 12 obj-$(CONFIG_MTD_ARM_INTEGRATOR)+= integrator-flash.o 13 obj-$(CONFIG_MTD_BAST) += bast-flash.o 14 obj-$(CONFIG_MTD_CFI_FLAGADM) += cfi_flagadm.o 15 obj-$(CONFIG_MTD_DC21285) += dc21285.o 16 obj-$(CONFIG_MTD_DILNETPC) += dilnetpc.o 17 obj-$(CONFIG_MTD_L440GX) += l440gx.o 18 obj-$(CONFIG_MTD_AMD76XROM) += amd76xrom.o 19 + obj-$(CONFIG_MTD_ESB2ROM) += esb2rom.o 20 obj-$(CONFIG_MTD_ICHXROM) += ichxrom.o 21 + obj-$(CONFIG_MTD_CK804XROM) += ck804xrom.o 22 obj-$(CONFIG_MTD_TSUNAMI) += tsunami_flash.o 23 obj-$(CONFIG_MTD_LUBBOCK) += lubbock-flash.o 24 obj-$(CONFIG_MTD_MAINSTONE) += mainstone-flash.o ··· 25 obj-$(CONFIG_MTD_CEIVA) += ceiva.o 26 obj-$(CONFIG_MTD_OCTAGON) += octagon-5066.o 27 obj-$(CONFIG_MTD_PHYSMAP) += physmap.o 28 + obj-$(CONFIG_MTD_PHYSMAP_OF) += physmap_of.o 29 obj-$(CONFIG_MTD_PNC2000) += pnc2000.o 30 obj-$(CONFIG_MTD_PCMCIA) += pcmciamtd.o 31 obj-$(CONFIG_MTD_RPXLITE) += rpxlite.o
+28 -6
drivers/mtd/maps/amd76xrom.c
··· 7 8 #include <linux/module.h> 9 #include <linux/types.h> 10 #include <linux/kernel.h> 11 #include <linux/init.h> 12 #include <asm/io.h> ··· 44 struct resource rsrc; 45 char map_name[sizeof(MOD_NAME) + 2 + ADDRESS_NAME_LEN]; 46 }; 47 48 static struct amd76xrom_window amd76xrom_window = { 49 .maps = LIST_HEAD_INIT(amd76xrom_window.maps), ··· 113 /* Remember the pci dev I find the window in - already have a ref */ 114 window->pdev = pdev; 115 116 /* Assume the rom window is properly setup, and find it's size */ 117 pci_read_config_byte(pdev, 0x43, &byte); 118 if ((byte & ((1<<7)|(1<<6))) == ((1<<7)|(1<<6))) { ··· 157 (unsigned long long)window->rsrc.end); 158 } 159 160 - #if 0 161 - 162 - /* Enable the selected rom window */ 163 - pci_read_config_byte(pdev, 0x43, &byte); 164 - pci_write_config_byte(pdev, 0x43, byte | rwindow->segen_bits); 165 - #endif 166 167 /* Enable writes through the rom window */ 168 pci_read_config_byte(pdev, 0x40, &byte);
··· 7 8 #include <linux/module.h> 9 #include <linux/types.h> 10 + #include <linux/version.h> 11 #include <linux/kernel.h> 12 #include <linux/init.h> 13 #include <asm/io.h> ··· 43 struct resource rsrc; 44 char map_name[sizeof(MOD_NAME) + 2 + ADDRESS_NAME_LEN]; 45 }; 46 + 47 + /* The 2 bits controlling the window size are often set to allow reading 48 + * the BIOS, but too small to allow writing, since the lock registers are 49 + * 4MiB lower in the address space than the data. 50 + * 51 + * This is intended to prevent flashing the bios, perhaps accidentally. 52 + * 53 + * This parameter allows the normal driver to over-ride the BIOS settings. 54 + * 55 + * The bits are 6 and 7. If both bits are set, it is a 5MiB window. 56 + * If only the 7 Bit is set, it is a 4MiB window. Otherwise, a 57 + * 64KiB window. 58 + * 59 + */ 60 + static uint win_size_bits; 61 + module_param(win_size_bits, uint, 0); 62 + MODULE_PARM_DESC(win_size_bits, "ROM window size bits override for 0x43 byte, normally set by BIOS."); 63 64 static struct amd76xrom_window amd76xrom_window = { 65 .maps = LIST_HEAD_INIT(amd76xrom_window.maps), ··· 95 /* Remember the pci dev I find the window in - already have a ref */ 96 window->pdev = pdev; 97 98 + /* Enable the selected rom window. This is often incorrectly 99 + * set up by the BIOS, and the 4MiB offset for the lock registers 100 + * requires the full 5MiB of window space. 101 + * 102 + * This 'write, then read' approach leaves the bits for 103 + * other uses of the hardware info. 104 + */ 105 + pci_read_config_byte(pdev, 0x43, &byte); 106 + pci_write_config_byte(pdev, 0x43, byte | win_size_bits ); 107 + 108 /* Assume the rom window is properly setup, and find it's size */ 109 pci_read_config_byte(pdev, 0x43, &byte); 110 if ((byte & ((1<<7)|(1<<6))) == ((1<<7)|(1<<6))) { ··· 129 (unsigned long long)window->rsrc.end); 130 } 131 132 133 /* Enable writes through the rom window */ 134 pci_read_config_byte(pdev, 0x40, &byte);
+1 -1
drivers/mtd/maps/bast-flash.c
··· 131 132 info->map.phys = res->start; 133 info->map.size = res->end - res->start + 1; 134 - info->map.name = pdev->dev.bus_id; 135 info->map.bankwidth = 2; 136 137 if (info->map.size > AREA_MAXSIZE)
··· 131 132 info->map.phys = res->start; 133 info->map.size = res->end - res->start + 1; 134 + info->map.name = pdev->dev.bus_id; 135 info->map.bankwidth = 2; 136 137 if (info->map.size > AREA_MAXSIZE)
+1 -2
drivers/mtd/maps/ceiva.c
··· 122 /* 123 * Allocate the map_info structs in one go. 124 */ 125 - maps = kmalloc(sizeof(struct map_info) * nr, GFP_KERNEL); 126 if (!maps) 127 return -ENOMEM; 128 - memset(maps, 0, sizeof(struct map_info) * nr); 129 /* 130 * Claim and then map the memory regions. 131 */
··· 122 /* 123 * Allocate the map_info structs in one go. 124 */ 125 + maps = kzalloc(sizeof(struct map_info) * nr, GFP_KERNEL); 126 if (!maps) 127 return -ENOMEM; 128 /* 129 * Claim and then map the memory regions. 130 */
+356
drivers/mtd/maps/ck804xrom.c
···
··· 1 + /* 2 + * ck804xrom.c 3 + * 4 + * Normal mappings of chips in physical memory 5 + * 6 + * Dave Olsen <dolsen@lnxi.com> 7 + * Ryan Jackson <rjackson@lnxi.com> 8 + */ 9 + 10 + #include <linux/module.h> 11 + #include <linux/types.h> 12 + #include <linux/version.h> 13 + #include <linux/kernel.h> 14 + #include <linux/init.h> 15 + #include <asm/io.h> 16 + #include <linux/mtd/mtd.h> 17 + #include <linux/mtd/map.h> 18 + #include <linux/mtd/cfi.h> 19 + #include <linux/mtd/flashchip.h> 20 + #include <linux/pci.h> 21 + #include <linux/pci_ids.h> 22 + #include <linux/list.h> 23 + 24 + 25 + #define MOD_NAME KBUILD_BASENAME 26 + 27 + #define ADDRESS_NAME_LEN 18 28 + 29 + #define ROM_PROBE_STEP_SIZE (64*1024) 30 + 31 + struct ck804xrom_window { 32 + void __iomem *virt; 33 + unsigned long phys; 34 + unsigned long size; 35 + struct list_head maps; 36 + struct resource rsrc; 37 + struct pci_dev *pdev; 38 + }; 39 + 40 + struct ck804xrom_map_info { 41 + struct list_head list; 42 + struct map_info map; 43 + struct mtd_info *mtd; 44 + struct resource rsrc; 45 + char map_name[sizeof(MOD_NAME) + 2 + ADDRESS_NAME_LEN]; 46 + }; 47 + 48 + 49 + /* The 2 bits controlling the window size are often set to allow reading 50 + * the BIOS, but too small to allow writing, since the lock registers are 51 + * 4MiB lower in the address space than the data. 52 + * 53 + * This is intended to prevent flashing the bios, perhaps accidentally. 54 + * 55 + * This parameter allows the normal driver to override the BIOS settings. 56 + * 57 + * The bits are 6 and 7. If both bits are set, it is a 5MiB window. 58 + * If only the 7 Bit is set, it is a 4MiB window. Otherwise, a 59 + * 64KiB window. 60 + * 61 + */ 62 + static uint win_size_bits = 0; 63 + module_param(win_size_bits, uint, 0); 64 + MODULE_PARM_DESC(win_size_bits, "ROM window size bits override for 0x88 byte, normally set by BIOS."); 65 + 66 + static struct ck804xrom_window ck804xrom_window = { 67 + .maps = LIST_HEAD_INIT(ck804xrom_window.maps), 68 + }; 69 + 70 + static void ck804xrom_cleanup(struct ck804xrom_window *window) 71 + { 72 + struct ck804xrom_map_info *map, *scratch; 73 + u8 byte; 74 + 75 + if (window->pdev) { 76 + /* Disable writes through the rom window */ 77 + pci_read_config_byte(window->pdev, 0x6d, &byte); 78 + pci_write_config_byte(window->pdev, 0x6d, byte & ~1); 79 + } 80 + 81 + /* Free all of the mtd devices */ 82 + list_for_each_entry_safe(map, scratch, &window->maps, list) { 83 + if (map->rsrc.parent) 84 + release_resource(&map->rsrc); 85 + 86 + del_mtd_device(map->mtd); 87 + map_destroy(map->mtd); 88 + list_del(&map->list); 89 + kfree(map); 90 + } 91 + if (window->rsrc.parent) 92 + release_resource(&window->rsrc); 93 + 94 + if (window->virt) { 95 + iounmap(window->virt); 96 + window->virt = NULL; 97 + window->phys = 0; 98 + window->size = 0; 99 + } 100 + pci_dev_put(window->pdev); 101 + } 102 + 103 + 104 + static int __devinit ck804xrom_init_one (struct pci_dev *pdev, 105 + const struct pci_device_id *ent) 106 + { 107 + static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL }; 108 + u8 byte; 109 + struct ck804xrom_window *window = &ck804xrom_window; 110 + struct ck804xrom_map_info *map = NULL; 111 + unsigned long map_top; 112 + 113 + /* Remember the pci dev I find the window in */ 114 + window->pdev = pci_dev_get(pdev); 115 + 116 + /* Enable the selected rom window. This is often incorrectly 117 + * set up by the BIOS, and the 4MiB offset for the lock registers 118 + * requires the full 5MiB of window space. 119 + * 120 + * This 'write, then read' approach leaves the bits for 121 + * other uses of the hardware info. 122 + */ 123 + pci_read_config_byte(pdev, 0x88, &byte); 124 + pci_write_config_byte(pdev, 0x88, byte | win_size_bits ); 125 + 126 + 127 + /* Assume the rom window is properly setup, and find it's size */ 128 + pci_read_config_byte(pdev, 0x88, &byte); 129 + 130 + if ((byte & ((1<<7)|(1<<6))) == ((1<<7)|(1<<6))) 131 + window->phys = 0xffb00000; /* 5MiB */ 132 + else if ((byte & (1<<7)) == (1<<7)) 133 + window->phys = 0xffc00000; /* 4MiB */ 134 + else 135 + window->phys = 0xffff0000; /* 64KiB */ 136 + 137 + window->size = 0xffffffffUL - window->phys + 1UL; 138 + 139 + /* 140 + * Try to reserve the window mem region. If this fails then 141 + * it is likely due to a fragment of the window being 142 + * "reserved" by the BIOS. In the case that the 143 + * request_mem_region() fails then once the rom size is 144 + * discovered we will try to reserve the unreserved fragment. 145 + */ 146 + window->rsrc.name = MOD_NAME; 147 + window->rsrc.start = window->phys; 148 + window->rsrc.end = window->phys + window->size - 1; 149 + window->rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY; 150 + if (request_resource(&iomem_resource, &window->rsrc)) { 151 + window->rsrc.parent = NULL; 152 + printk(KERN_ERR MOD_NAME 153 + " %s(): Unable to register resource" 154 + " 0x%.016llx-0x%.016llx - kernel bug?\n", 155 + __func__, 156 + (unsigned long long)window->rsrc.start, 157 + (unsigned long long)window->rsrc.end); 158 + } 159 + 160 + 161 + /* Enable writes through the rom window */ 162 + pci_read_config_byte(pdev, 0x6d, &byte); 163 + pci_write_config_byte(pdev, 0x6d, byte | 1); 164 + 165 + /* FIXME handle registers 0x80 - 0x8C the bios region locks */ 166 + 167 + /* For write accesses caches are useless */ 168 + window->virt = ioremap_nocache(window->phys, window->size); 169 + if (!window->virt) { 170 + printk(KERN_ERR MOD_NAME ": ioremap(%08lx, %08lx) failed\n", 171 + window->phys, window->size); 172 + goto out; 173 + } 174 + 175 + /* Get the first address to look for a rom chip at */ 176 + map_top = window->phys; 177 + #if 1 178 + /* The probe sequence run over the firmware hub lock 179 + * registers sets them to 0x7 (no access). 180 + * Probe at most the last 4MiB of the address space. 181 + */ 182 + if (map_top < 0xffc00000) 183 + map_top = 0xffc00000; 184 + #endif 185 + /* Loop through and look for rom chips. Since we don't know the 186 + * starting address for each chip, probe every ROM_PROBE_STEP_SIZE 187 + * bytes from the starting address of the window. 188 + */ 189 + while((map_top - 1) < 0xffffffffUL) { 190 + struct cfi_private *cfi; 191 + unsigned long offset; 192 + int i; 193 + 194 + if (!map) 195 + map = kmalloc(sizeof(*map), GFP_KERNEL); 196 + 197 + if (!map) { 198 + printk(KERN_ERR MOD_NAME ": kmalloc failed"); 199 + goto out; 200 + } 201 + memset(map, 0, sizeof(*map)); 202 + INIT_LIST_HEAD(&map->list); 203 + map->map.name = map->map_name; 204 + map->map.phys = map_top; 205 + offset = map_top - window->phys; 206 + map->map.virt = (void __iomem *) 207 + (((unsigned long)(window->virt)) + offset); 208 + map->map.size = 0xffffffffUL - map_top + 1UL; 209 + /* Set the name of the map to the address I am trying */ 210 + sprintf(map->map_name, "%s @%08lx", 211 + MOD_NAME, map->map.phys); 212 + 213 + /* There is no generic VPP support */ 214 + for(map->map.bankwidth = 32; map->map.bankwidth; 215 + map->map.bankwidth >>= 1) 216 + { 217 + char **probe_type; 218 + /* Skip bankwidths that are not supported */ 219 + if (!map_bankwidth_supported(map->map.bankwidth)) 220 + continue; 221 + 222 + /* Setup the map methods */ 223 + simple_map_init(&map->map); 224 + 225 + /* Try all of the probe methods */ 226 + probe_type = rom_probe_types; 227 + for(; *probe_type; probe_type++) { 228 + map->mtd = do_map_probe(*probe_type, &map->map); 229 + if (map->mtd) 230 + goto found; 231 + } 232 + } 233 + map_top += ROM_PROBE_STEP_SIZE; 234 + continue; 235 + found: 236 + /* Trim the size if we are larger than the map */ 237 + if (map->mtd->size > map->map.size) { 238 + printk(KERN_WARNING MOD_NAME 239 + " rom(%u) larger than window(%lu). fixing...\n", 240 + map->mtd->size, map->map.size); 241 + map->mtd->size = map->map.size; 242 + } 243 + if (window->rsrc.parent) { 244 + /* 245 + * Registering the MTD device in iomem may not be possible 246 + * if there is a BIOS "reserved" and BUSY range. If this 247 + * fails then continue anyway. 248 + */ 249 + map->rsrc.name = map->map_name; 250 + map->rsrc.start = map->map.phys; 251 + map->rsrc.end = map->map.phys + map->mtd->size - 1; 252 + map->rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY; 253 + if (request_resource(&window->rsrc, &map->rsrc)) { 254 + printk(KERN_ERR MOD_NAME 255 + ": cannot reserve MTD resource\n"); 256 + map->rsrc.parent = NULL; 257 + } 258 + } 259 + 260 + /* Make the whole region visible in the map */ 261 + map->map.virt = window->virt; 262 + map->map.phys = window->phys; 263 + cfi = map->map.fldrv_priv; 264 + for(i = 0; i < cfi->numchips; i++) 265 + cfi->chips[i].start += offset; 266 + 267 + /* Now that the mtd devices is complete claim and export it */ 268 + map->mtd->owner = THIS_MODULE; 269 + if (add_mtd_device(map->mtd)) { 270 + map_destroy(map->mtd); 271 + map->mtd = NULL; 272 + goto out; 273 + } 274 + 275 + 276 + /* Calculate the new value of map_top */ 277 + map_top += map->mtd->size; 278 + 279 + /* File away the map structure */ 280 + list_add(&map->list, &window->maps); 281 + map = NULL; 282 + } 283 + 284 + out: 285 + /* Free any left over map structures */ 286 + if (map) 287 + kfree(map); 288 + 289 + /* See if I have any map structures */ 290 + if (list_empty(&window->maps)) { 291 + ck804xrom_cleanup(window); 292 + return -ENODEV; 293 + } 294 + return 0; 295 + } 296 + 297 + 298 + static void __devexit ck804xrom_remove_one (struct pci_dev *pdev) 299 + { 300 + struct ck804xrom_window *window = &ck804xrom_window; 301 + 302 + ck804xrom_cleanup(window); 303 + } 304 + 305 + static struct pci_device_id ck804xrom_pci_tbl[] = { 306 + { PCI_VENDOR_ID_NVIDIA, 0x0051, 307 + PCI_ANY_ID, PCI_ANY_ID, }, /* nvidia ck804 */ 308 + { 0, } 309 + }; 310 + 311 + MODULE_DEVICE_TABLE(pci, ck804xrom_pci_tbl); 312 + 313 + #if 0 314 + static struct pci_driver ck804xrom_driver = { 315 + .name = MOD_NAME, 316 + .id_table = ck804xrom_pci_tbl, 317 + .probe = ck804xrom_init_one, 318 + .remove = ck804xrom_remove_one, 319 + }; 320 + #endif 321 + 322 + static int __init init_ck804xrom(void) 323 + { 324 + struct pci_dev *pdev; 325 + struct pci_device_id *id; 326 + int retVal; 327 + pdev = NULL; 328 + 329 + for(id = ck804xrom_pci_tbl; id->vendor; id++) { 330 + pdev = pci_find_device(id->vendor, id->device, NULL); 331 + if (pdev) 332 + break; 333 + } 334 + if (pdev) { 335 + retVal = ck804xrom_init_one(pdev, &ck804xrom_pci_tbl[0]); 336 + pci_dev_put(pdev); 337 + return retVal; 338 + } 339 + return -ENXIO; 340 + #if 0 341 + return pci_module_init(&ck804xrom_driver); 342 + #endif 343 + } 344 + 345 + static void __exit cleanup_ck804xrom(void) 346 + { 347 + ck804xrom_remove_one(ck804xrom_window.pdev); 348 + } 349 + 350 + module_init(init_ck804xrom); 351 + module_exit(cleanup_ck804xrom); 352 + 353 + MODULE_LICENSE("GPL"); 354 + MODULE_AUTHOR("Eric Biederman <ebiederman@lnxi.com>, Dave Olsen <dolsen@lnxi.com>"); 355 + MODULE_DESCRIPTION("MTD map driver for BIOS chips on the Nvidia ck804 southbridge"); 356 +
-283
drivers/mtd/maps/cstm_mips_ixx.c
··· 1 - /* 2 - * $Id: cstm_mips_ixx.c,v 1.14 2005/11/07 11:14:26 gleixner Exp $ 3 - * 4 - * Mapping of a custom board with both AMD CFI and JEDEC flash in partitions. 5 - * Config with both CFI and JEDEC device support. 6 - * 7 - * Basically physmap.c with the addition of partitions and 8 - * an array of mapping info to accomodate more than one flash type per board. 9 - * 10 - * Copyright 2000 MontaVista Software Inc. 11 - * 12 - * This program is free software; you can redistribute it and/or modify it 13 - * under the terms of the GNU General Public License as published by the 14 - * Free Software Foundation; either version 2 of the License, or (at your 15 - * option) any later version. 16 - * 17 - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 18 - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19 - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 20 - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 23 - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 24 - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 - * 28 - * You should have received a copy of the GNU General Public License along 29 - * with this program; if not, write to the Free Software Foundation, Inc., 30 - * 675 Mass Ave, Cambridge, MA 02139, USA. 31 - */ 32 - 33 - #include <linux/module.h> 34 - #include <linux/types.h> 35 - #include <linux/kernel.h> 36 - #include <linux/init.h> 37 - #include <asm/io.h> 38 - #include <linux/mtd/mtd.h> 39 - #include <linux/mtd/map.h> 40 - #include <linux/mtd/partitions.h> 41 - #include <linux/delay.h> 42 - 43 - #if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) 44 - #define CC_GCR 0xB4013818 45 - #define CC_GPBCR 0xB401380A 46 - #define CC_GPBDR 0xB4013808 47 - #define CC_M68K_DEVICE 1 48 - #define CC_M68K_FUNCTION 6 49 - #define CC_CONFADDR 0xB8004000 50 - #define CC_CONFDATA 0xB8004004 51 - #define CC_FC_FCR 0xB8002004 52 - #define CC_FC_DCR 0xB8002008 53 - #define CC_GPACR 0xB4013802 54 - #define CC_GPAICR 0xB4013804 55 - #endif /* defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) */ 56 - 57 - #if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) 58 - void cstm_mips_ixx_set_vpp(struct map_info *map,int vpp) 59 - { 60 - static DEFINE_SPINLOCK(vpp_lock); 61 - static int vpp_count = 0; 62 - unsigned long flags; 63 - 64 - spin_lock_irqsave(&vpp_lock, flags); 65 - 66 - if (vpp) { 67 - if (!vpp_count++) { 68 - __u16 data; 69 - __u8 data1; 70 - static u8 first = 1; 71 - 72 - // Set GPIO port B pin3 to high 73 - data = *(__u16 *)(CC_GPBCR); 74 - data = (data & 0xff0f) | 0x0040; 75 - *(__u16 *)CC_GPBCR = data; 76 - *(__u8 *)CC_GPBDR = (*(__u8*)CC_GPBDR) | 0x08; 77 - if (first) { 78 - first = 0; 79 - /* need to have this delay for first 80 - enabling vpp after powerup */ 81 - udelay(40); 82 - } 83 - } 84 - } else { 85 - if (!--vpp_count) { 86 - __u16 data; 87 - 88 - // Set GPIO port B pin3 to high 89 - data = *(__u16 *)(CC_GPBCR); 90 - data = (data & 0xff3f) | 0x0040; 91 - *(__u16 *)CC_GPBCR = data; 92 - *(__u8 *)CC_GPBDR = (*(__u8*)CC_GPBDR) & 0xf7; 93 - } 94 - } 95 - spin_unlock_irqrestore(&vpp_lock, flags); 96 - } 97 - #endif 98 - 99 - /* board and partition description */ 100 - 101 - #define MAX_PHYSMAP_PARTITIONS 8 102 - struct cstm_mips_ixx_info { 103 - char *name; 104 - unsigned long window_addr; 105 - unsigned long window_size; 106 - int bankwidth; 107 - int num_partitions; 108 - }; 109 - 110 - #if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) 111 - #define PHYSMAP_NUMBER 1 // number of board desc structs needed, one per contiguous flash type 112 - const struct cstm_mips_ixx_info cstm_mips_ixx_board_desc[PHYSMAP_NUMBER] = 113 - { 114 - { // 28F128J3A in 2x16 configuration 115 - "big flash", // name 116 - 0x08000000, // window_addr 117 - 0x02000000, // window_size 118 - 4, // bankwidth 119 - 1, // num_partitions 120 - } 121 - 122 - }; 123 - static struct mtd_partition cstm_mips_ixx_partitions[PHYSMAP_NUMBER][MAX_PHYSMAP_PARTITIONS] = { 124 - { // 28F128J3A in 2x16 configuration 125 - { 126 - .name = "main partition ", 127 - .size = 0x02000000, // 128 x 2 x 128k byte sectors 128 - .offset = 0, 129 - }, 130 - }, 131 - }; 132 - #else /* defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) */ 133 - #define PHYSMAP_NUMBER 1 // number of board desc structs needed, one per contiguous flash type 134 - const struct cstm_mips_ixx_info cstm_mips_ixx_board_desc[PHYSMAP_NUMBER] = 135 - { 136 - { 137 - "MTD flash", // name 138 - CONFIG_MTD_CSTM_MIPS_IXX_START, // window_addr 139 - CONFIG_MTD_CSTM_MIPS_IXX_LEN, // window_size 140 - CONFIG_MTD_CSTM_MIPS_IXX_BUSWIDTH, // bankwidth 141 - 1, // num_partitions 142 - }, 143 - 144 - }; 145 - static struct mtd_partition cstm_mips_ixx_partitions[PHYSMAP_NUMBER][MAX_PHYSMAP_PARTITIONS] = { 146 - { 147 - { 148 - .name = "main partition", 149 - .size = CONFIG_MTD_CSTM_MIPS_IXX_LEN, 150 - .offset = 0, 151 - }, 152 - }, 153 - }; 154 - #endif /* defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) */ 155 - 156 - struct map_info cstm_mips_ixx_map[PHYSMAP_NUMBER]; 157 - 158 - int __init init_cstm_mips_ixx(void) 159 - { 160 - int i; 161 - int jedec; 162 - struct mtd_info *mymtd; 163 - struct mtd_partition *parts; 164 - 165 - /* Initialize mapping */ 166 - for (i=0;i<PHYSMAP_NUMBER;i++) { 167 - printk(KERN_NOTICE "cstm_mips_ixx flash device: 0x%lx at 0x%lx\n", 168 - cstm_mips_ixx_board_desc[i].window_size, cstm_mips_ixx_board_desc[i].window_addr); 169 - 170 - 171 - cstm_mips_ixx_map[i].phys = cstm_mips_ixx_board_desc[i].window_addr; 172 - cstm_mips_ixx_map[i].virt = ioremap(cstm_mips_ixx_board_desc[i].window_addr, cstm_mips_ixx_board_desc[i].window_size); 173 - if (!cstm_mips_ixx_map[i].virt) { 174 - int j = 0; 175 - printk(KERN_WARNING "Failed to ioremap\n"); 176 - for (j = 0; j < i; j++) { 177 - if (cstm_mips_ixx_map[j].virt) { 178 - iounmap(cstm_mips_ixx_map[j].virt); 179 - cstm_mips_ixx_map[j].virt = NULL; 180 - } 181 - } 182 - return -EIO; 183 - } 184 - cstm_mips_ixx_map[i].name = cstm_mips_ixx_board_desc[i].name; 185 - cstm_mips_ixx_map[i].size = cstm_mips_ixx_board_desc[i].window_size; 186 - cstm_mips_ixx_map[i].bankwidth = cstm_mips_ixx_board_desc[i].bankwidth; 187 - #if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) 188 - cstm_mips_ixx_map[i].set_vpp = cstm_mips_ixx_set_vpp; 189 - #endif 190 - simple_map_init(&cstm_mips_ixx_map[i]); 191 - //printk(KERN_NOTICE "cstm_mips_ixx: ioremap is %x\n",(unsigned int)(cstm_mips_ixx_map[i].virt)); 192 - } 193 - 194 - #if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) 195 - setup_ITE_IVR_flash(); 196 - #endif /* defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) */ 197 - 198 - for (i=0;i<PHYSMAP_NUMBER;i++) { 199 - parts = &cstm_mips_ixx_partitions[i][0]; 200 - jedec = 0; 201 - mymtd = (struct mtd_info *)do_map_probe("cfi_probe", &cstm_mips_ixx_map[i]); 202 - //printk(KERN_NOTICE "phymap %d cfi_probe: mymtd is %x\n",i,(unsigned int)mymtd); 203 - if (!mymtd) { 204 - jedec = 1; 205 - mymtd = (struct mtd_info *)do_map_probe("jedec", &cstm_mips_ixx_map[i]); 206 - printk(KERN_NOTICE "cstm_mips_ixx %d jedec: mymtd is %x\n",i,(unsigned int)mymtd); 207 - } 208 - if (mymtd) { 209 - mymtd->owner = THIS_MODULE; 210 - 211 - cstm_mips_ixx_map[i].map_priv_2 = (unsigned long)mymtd; 212 - add_mtd_partitions(mymtd, parts, cstm_mips_ixx_board_desc[i].num_partitions); 213 - } 214 - else { 215 - for (i = 0; i < PHYSMAP_NUMBER; i++) { 216 - if (cstm_mips_ixx_map[i].virt) { 217 - iounmap(cstm_mips_ixx_map[i].virt); 218 - cstm_mips_ixx_map[i].virt = NULL; 219 - } 220 - } 221 - return -ENXIO; 222 - } 223 - } 224 - return 0; 225 - } 226 - 227 - static void __exit cleanup_cstm_mips_ixx(void) 228 - { 229 - int i; 230 - struct mtd_info *mymtd; 231 - 232 - for (i=0;i<PHYSMAP_NUMBER;i++) { 233 - mymtd = (struct mtd_info *)cstm_mips_ixx_map[i].map_priv_2; 234 - if (mymtd) { 235 - del_mtd_partitions(mymtd); 236 - map_destroy(mymtd); 237 - } 238 - if (cstm_mips_ixx_map[i].virt) { 239 - iounmap((void *)cstm_mips_ixx_map[i].virt); 240 - cstm_mips_ixx_map[i].virt = 0; 241 - } 242 - } 243 - } 244 - #if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) 245 - void PCISetULongByOffset(__u32 DevNumber, __u32 FuncNumber, __u32 Offset, __u32 data) 246 - { 247 - __u32 offset; 248 - 249 - offset = ( unsigned long )( 0x80000000 | ( DevNumber << 11 ) + ( FuncNumber << 8 ) + Offset) ; 250 - 251 - *(__u32 *)CC_CONFADDR = offset; 252 - *(__u32 *)CC_CONFDATA = data; 253 - } 254 - void setup_ITE_IVR_flash() 255 - { 256 - __u32 size, base; 257 - 258 - size = 0x0e000000; // 32MiB 259 - base = (0x08000000) >> 8 >>1; // Bug: we must shift one more bit 260 - 261 - /* need to set ITE flash to 32 bits instead of default 8 */ 262 - #ifdef CONFIG_MIPS_IVR 263 - *(__u32 *)CC_FC_FCR = 0x55; 264 - *(__u32 *)CC_GPACR = 0xfffc; 265 - #else 266 - *(__u32 *)CC_FC_FCR = 0x77; 267 - #endif 268 - /* turn bursting off */ 269 - *(__u32 *)CC_FC_DCR = 0x0; 270 - 271 - /* setup for one chip 4 byte PCI access */ 272 - PCISetULongByOffset(CC_M68K_DEVICE, CC_M68K_FUNCTION, 0x60, size | base); 273 - PCISetULongByOffset(CC_M68K_DEVICE, CC_M68K_FUNCTION, 0x64, 0x02); 274 - } 275 - #endif /* defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) */ 276 - 277 - module_init(init_cstm_mips_ixx); 278 - module_exit(cleanup_cstm_mips_ixx); 279 - 280 - 281 - MODULE_LICENSE("GPL"); 282 - MODULE_AUTHOR("Alice Hennessy <ahennessy@mvista.com>"); 283 - MODULE_DESCRIPTION("MTD map driver for ITE 8172G and Globespan IVR boards");
···
+450
drivers/mtd/maps/esb2rom.c
···
··· 1 + /* 2 + * esb2rom.c 3 + * 4 + * Normal mappings of flash chips in physical memory 5 + * through the Intel ESB2 Southbridge. 6 + * 7 + * This was derived from ichxrom.c in May 2006 by 8 + * Lew Glendenning <lglendenning@lnxi.com> 9 + * 10 + * Eric Biederman, of course, was a major help in this effort. 11 + */ 12 + 13 + #include <linux/module.h> 14 + #include <linux/types.h> 15 + #include <linux/version.h> 16 + #include <linux/kernel.h> 17 + #include <linux/init.h> 18 + #include <asm/io.h> 19 + #include <linux/mtd/mtd.h> 20 + #include <linux/mtd/map.h> 21 + #include <linux/mtd/cfi.h> 22 + #include <linux/mtd/flashchip.h> 23 + #include <linux/pci.h> 24 + #include <linux/pci_ids.h> 25 + #include <linux/list.h> 26 + 27 + #define MOD_NAME KBUILD_BASENAME 28 + 29 + #define ADDRESS_NAME_LEN 18 30 + 31 + #define ROM_PROBE_STEP_SIZE (64*1024) /* 64KiB */ 32 + 33 + #define BIOS_CNTL 0xDC 34 + #define BIOS_LOCK_ENABLE 0x02 35 + #define BIOS_WRITE_ENABLE 0x01 36 + 37 + /* This became a 16-bit register, and EN2 has disappeared */ 38 + #define FWH_DEC_EN1 0xD8 39 + #define FWH_F8_EN 0x8000 40 + #define FWH_F0_EN 0x4000 41 + #define FWH_E8_EN 0x2000 42 + #define FWH_E0_EN 0x1000 43 + #define FWH_D8_EN 0x0800 44 + #define FWH_D0_EN 0x0400 45 + #define FWH_C8_EN 0x0200 46 + #define FWH_C0_EN 0x0100 47 + #define FWH_LEGACY_F_EN 0x0080 48 + #define FWH_LEGACY_E_EN 0x0040 49 + /* reserved 0x0020 and 0x0010 */ 50 + #define FWH_70_EN 0x0008 51 + #define FWH_60_EN 0x0004 52 + #define FWH_50_EN 0x0002 53 + #define FWH_40_EN 0x0001 54 + 55 + /* these are 32-bit values */ 56 + #define FWH_SEL1 0xD0 57 + #define FWH_SEL2 0xD4 58 + 59 + #define FWH_8MiB (FWH_F8_EN | FWH_F0_EN | FWH_E8_EN | FWH_E0_EN | \ 60 + FWH_D8_EN | FWH_D0_EN | FWH_C8_EN | FWH_C0_EN | \ 61 + FWH_70_EN | FWH_60_EN | FWH_50_EN | FWH_40_EN) 62 + 63 + #define FWH_7MiB (FWH_F8_EN | FWH_F0_EN | FWH_E8_EN | FWH_E0_EN | \ 64 + FWH_D8_EN | FWH_D0_EN | FWH_C8_EN | FWH_C0_EN | \ 65 + FWH_70_EN | FWH_60_EN | FWH_50_EN) 66 + 67 + #define FWH_6MiB (FWH_F8_EN | FWH_F0_EN | FWH_E8_EN | FWH_E0_EN | \ 68 + FWH_D8_EN | FWH_D0_EN | FWH_C8_EN | FWH_C0_EN | \ 69 + FWH_70_EN | FWH_60_EN) 70 + 71 + #define FWH_5MiB (FWH_F8_EN | FWH_F0_EN | FWH_E8_EN | FWH_E0_EN | \ 72 + FWH_D8_EN | FWH_D0_EN | FWH_C8_EN | FWH_C0_EN | \ 73 + FWH_70_EN) 74 + 75 + #define FWH_4MiB (FWH_F8_EN | FWH_F0_EN | FWH_E8_EN | FWH_E0_EN | \ 76 + FWH_D8_EN | FWH_D0_EN | FWH_C8_EN | FWH_C0_EN) 77 + 78 + #define FWH_3_5MiB (FWH_F8_EN | FWH_F0_EN | FWH_E8_EN | FWH_E0_EN | \ 79 + FWH_D8_EN | FWH_D0_EN | FWH_C8_EN) 80 + 81 + #define FWH_3MiB (FWH_F8_EN | FWH_F0_EN | FWH_E8_EN | FWH_E0_EN | \ 82 + FWH_D8_EN | FWH_D0_EN) 83 + 84 + #define FWH_2_5MiB (FWH_F8_EN | FWH_F0_EN | FWH_E8_EN | FWH_E0_EN | \ 85 + FWH_D8_EN) 86 + 87 + #define FWH_2MiB (FWH_F8_EN | FWH_F0_EN | FWH_E8_EN | FWH_E0_EN) 88 + 89 + #define FWH_1_5MiB (FWH_F8_EN | FWH_F0_EN | FWH_E8_EN) 90 + 91 + #define FWH_1MiB (FWH_F8_EN | FWH_F0_EN) 92 + 93 + #define FWH_0_5MiB (FWH_F8_EN) 94 + 95 + 96 + struct esb2rom_window { 97 + void __iomem* virt; 98 + unsigned long phys; 99 + unsigned long size; 100 + struct list_head maps; 101 + struct resource rsrc; 102 + struct pci_dev *pdev; 103 + }; 104 + 105 + struct esb2rom_map_info { 106 + struct list_head list; 107 + struct map_info map; 108 + struct mtd_info *mtd; 109 + struct resource rsrc; 110 + char map_name[sizeof(MOD_NAME) + 2 + ADDRESS_NAME_LEN]; 111 + }; 112 + 113 + static struct esb2rom_window esb2rom_window = { 114 + .maps = LIST_HEAD_INIT(esb2rom_window.maps), 115 + }; 116 + 117 + static void esb2rom_cleanup(struct esb2rom_window *window) 118 + { 119 + struct esb2rom_map_info *map, *scratch; 120 + u8 byte; 121 + 122 + /* Disable writes through the rom window */ 123 + pci_read_config_byte(window->pdev, BIOS_CNTL, &byte); 124 + pci_write_config_byte(window->pdev, BIOS_CNTL, 125 + byte & ~BIOS_WRITE_ENABLE); 126 + 127 + /* Free all of the mtd devices */ 128 + list_for_each_entry_safe(map, scratch, &window->maps, list) { 129 + if (map->rsrc.parent) 130 + release_resource(&map->rsrc); 131 + del_mtd_device(map->mtd); 132 + map_destroy(map->mtd); 133 + list_del(&map->list); 134 + kfree(map); 135 + } 136 + if (window->rsrc.parent) 137 + release_resource(&window->rsrc); 138 + if (window->virt) { 139 + iounmap(window->virt); 140 + window->virt = NULL; 141 + window->phys = 0; 142 + window->size = 0; 143 + } 144 + pci_dev_put(window->pdev); 145 + } 146 + 147 + static int __devinit esb2rom_init_one(struct pci_dev *pdev, 148 + const struct pci_device_id *ent) 149 + { 150 + static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL }; 151 + struct esb2rom_window *window = &esb2rom_window; 152 + struct esb2rom_map_info *map = NULL; 153 + unsigned long map_top; 154 + u8 byte; 155 + u16 word; 156 + 157 + /* For now I just handle the ecb2 and I assume there 158 + * are not a lot of resources up at the top of the address 159 + * space. It is possible to handle other devices in the 160 + * top 16MiB but it is very painful. Also since 161 + * you can only really attach a FWH to an ICHX there 162 + * a number of simplifications you can make. 163 + * 164 + * Also you can page firmware hubs if an 8MiB window isn't enough 165 + * but don't currently handle that case either. 166 + */ 167 + window->pdev = pci_dev_get(pdev); 168 + 169 + /* RLG: experiment 2. Force the window registers to the widest values */ 170 + 171 + /* 172 + pci_read_config_word(pdev, FWH_DEC_EN1, &word); 173 + printk(KERN_DEBUG "Original FWH_DEC_EN1 : %x\n", word); 174 + pci_write_config_byte(pdev, FWH_DEC_EN1, 0xff); 175 + pci_read_config_byte(pdev, FWH_DEC_EN1, &byte); 176 + printk(KERN_DEBUG "New FWH_DEC_EN1 : %x\n", byte); 177 + 178 + pci_read_config_byte(pdev, FWH_DEC_EN2, &byte); 179 + printk(KERN_DEBUG "Original FWH_DEC_EN2 : %x\n", byte); 180 + pci_write_config_byte(pdev, FWH_DEC_EN2, 0x0f); 181 + pci_read_config_byte(pdev, FWH_DEC_EN2, &byte); 182 + printk(KERN_DEBUG "New FWH_DEC_EN2 : %x\n", byte); 183 + */ 184 + 185 + /* Find a region continuous to the end of the ROM window */ 186 + window->phys = 0; 187 + pci_read_config_word(pdev, FWH_DEC_EN1, &word); 188 + printk(KERN_DEBUG "pci_read_config_byte : %x\n", word); 189 + 190 + if ((word & FWH_8MiB) == FWH_8MiB) 191 + window->phys = 0xff400000; 192 + else if ((word & FWH_7MiB) == FWH_7MiB) 193 + window->phys = 0xff500000; 194 + else if ((word & FWH_6MiB) == FWH_6MiB) 195 + window->phys = 0xff600000; 196 + else if ((word & FWH_5MiB) == FWH_5MiB) 197 + window->phys = 0xFF700000; 198 + else if ((word & FWH_4MiB) == FWH_4MiB) 199 + window->phys = 0xffc00000; 200 + else if ((word & FWH_3_5MiB) == FWH_3_5MiB) 201 + window->phys = 0xffc80000; 202 + else if ((word & FWH_3MiB) == FWH_3MiB) 203 + window->phys = 0xffd00000; 204 + else if ((word & FWH_2_5MiB) == FWH_2_5MiB) 205 + window->phys = 0xffd80000; 206 + else if ((word & FWH_2MiB) == FWH_2MiB) 207 + window->phys = 0xffe00000; 208 + else if ((word & FWH_1_5MiB) == FWH_1_5MiB) 209 + window->phys = 0xffe80000; 210 + else if ((word & FWH_1MiB) == FWH_1MiB) 211 + window->phys = 0xfff00000; 212 + else if ((word & FWH_0_5MiB) == FWH_0_5MiB) 213 + window->phys = 0xfff80000; 214 + 215 + /* reserved 0x0020 and 0x0010 */ 216 + window->phys -= 0x400000UL; 217 + window->size = (0xffffffffUL - window->phys) + 1UL; 218 + 219 + /* Enable writes through the rom window */ 220 + pci_read_config_byte(pdev, BIOS_CNTL, &byte); 221 + if (!(byte & BIOS_WRITE_ENABLE) && (byte & (BIOS_LOCK_ENABLE))) { 222 + /* The BIOS will generate an error if I enable 223 + * this device, so don't even try. 224 + */ 225 + printk(KERN_ERR MOD_NAME ": firmware access control, I can't enable writes\n"); 226 + goto out; 227 + } 228 + pci_write_config_byte(pdev, BIOS_CNTL, byte | BIOS_WRITE_ENABLE); 229 + 230 + /* 231 + * Try to reserve the window mem region. If this fails then 232 + * it is likely due to the window being "reseved" by the BIOS. 233 + */ 234 + window->rsrc.name = MOD_NAME; 235 + window->rsrc.start = window->phys; 236 + window->rsrc.end = window->phys + window->size - 1; 237 + window->rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY; 238 + if (request_resource(&iomem_resource, &window->rsrc)) { 239 + window->rsrc.parent = NULL; 240 + printk(KERN_DEBUG MOD_NAME 241 + ": %s(): Unable to register resource" 242 + " 0x%.08llx-0x%.08llx - kernel bug?\n", 243 + __func__, 244 + (unsigned long long)window->rsrc.start, 245 + (unsigned long long)window->rsrc.end); 246 + } 247 + 248 + /* Map the firmware hub into my address space. */ 249 + window->virt = ioremap_nocache(window->phys, window->size); 250 + if (!window->virt) { 251 + printk(KERN_ERR MOD_NAME ": ioremap(%08lx, %08lx) failed\n", 252 + window->phys, window->size); 253 + goto out; 254 + } 255 + 256 + /* Get the first address to look for an rom chip at */ 257 + map_top = window->phys; 258 + if ((window->phys & 0x3fffff) != 0) { 259 + /* if not aligned on 4MiB, look 4MiB lower in address space */ 260 + map_top = window->phys + 0x400000; 261 + } 262 + #if 1 263 + /* The probe sequence run over the firmware hub lock 264 + * registers sets them to 0x7 (no access). 265 + * (Insane hardware design, but most copied Intel's.) 266 + * ==> Probe at most the last 4M of the address space. 267 + */ 268 + if (map_top < 0xffc00000) 269 + map_top = 0xffc00000; 270 + #endif 271 + /* Loop through and look for rom chips */ 272 + while ((map_top - 1) < 0xffffffffUL) { 273 + struct cfi_private *cfi; 274 + unsigned long offset; 275 + int i; 276 + 277 + if (!map) 278 + map = kmalloc(sizeof(*map), GFP_KERNEL); 279 + if (!map) { 280 + printk(KERN_ERR MOD_NAME ": kmalloc failed"); 281 + goto out; 282 + } 283 + memset(map, 0, sizeof(*map)); 284 + INIT_LIST_HEAD(&map->list); 285 + map->map.name = map->map_name; 286 + map->map.phys = map_top; 287 + offset = map_top - window->phys; 288 + map->map.virt = (void __iomem *) 289 + (((unsigned long)(window->virt)) + offset); 290 + map->map.size = 0xffffffffUL - map_top + 1UL; 291 + /* Set the name of the map to the address I am trying */ 292 + sprintf(map->map_name, "%s @%08lx", 293 + MOD_NAME, map->map.phys); 294 + 295 + /* Firmware hubs only use vpp when being programmed 296 + * in a factory setting. So in-place programming 297 + * needs to use a different method. 298 + */ 299 + for(map->map.bankwidth = 32; map->map.bankwidth; 300 + map->map.bankwidth >>= 1) { 301 + char **probe_type; 302 + /* Skip bankwidths that are not supported */ 303 + if (!map_bankwidth_supported(map->map.bankwidth)) 304 + continue; 305 + 306 + /* Setup the map methods */ 307 + simple_map_init(&map->map); 308 + 309 + /* Try all of the probe methods */ 310 + probe_type = rom_probe_types; 311 + for(; *probe_type; probe_type++) { 312 + map->mtd = do_map_probe(*probe_type, &map->map); 313 + if (map->mtd) 314 + goto found; 315 + } 316 + } 317 + map_top += ROM_PROBE_STEP_SIZE; 318 + continue; 319 + found: 320 + /* Trim the size if we are larger than the map */ 321 + if (map->mtd->size > map->map.size) { 322 + printk(KERN_WARNING MOD_NAME 323 + " rom(%u) larger than window(%lu). fixing...\n", 324 + map->mtd->size, map->map.size); 325 + map->mtd->size = map->map.size; 326 + } 327 + if (window->rsrc.parent) { 328 + /* 329 + * Registering the MTD device in iomem may not be possible 330 + * if there is a BIOS "reserved" and BUSY range. If this 331 + * fails then continue anyway. 332 + */ 333 + map->rsrc.name = map->map_name; 334 + map->rsrc.start = map->map.phys; 335 + map->rsrc.end = map->map.phys + map->mtd->size - 1; 336 + map->rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY; 337 + if (request_resource(&window->rsrc, &map->rsrc)) { 338 + printk(KERN_ERR MOD_NAME 339 + ": cannot reserve MTD resource\n"); 340 + map->rsrc.parent = NULL; 341 + } 342 + } 343 + 344 + /* Make the whole region visible in the map */ 345 + map->map.virt = window->virt; 346 + map->map.phys = window->phys; 347 + cfi = map->map.fldrv_priv; 348 + for(i = 0; i < cfi->numchips; i++) 349 + cfi->chips[i].start += offset; 350 + 351 + /* Now that the mtd devices is complete claim and export it */ 352 + map->mtd->owner = THIS_MODULE; 353 + if (add_mtd_device(map->mtd)) { 354 + map_destroy(map->mtd); 355 + map->mtd = NULL; 356 + goto out; 357 + } 358 + 359 + /* Calculate the new value of map_top */ 360 + map_top += map->mtd->size; 361 + 362 + /* File away the map structure */ 363 + list_add(&map->list, &window->maps); 364 + map = NULL; 365 + } 366 + 367 + out: 368 + /* Free any left over map structures */ 369 + kfree(map); 370 + 371 + /* See if I have any map structures */ 372 + if (list_empty(&window->maps)) { 373 + esb2rom_cleanup(window); 374 + return -ENODEV; 375 + } 376 + return 0; 377 + } 378 + 379 + static void __devexit esb2rom_remove_one (struct pci_dev *pdev) 380 + { 381 + struct esb2rom_window *window = &esb2rom_window; 382 + esb2rom_cleanup(window); 383 + } 384 + 385 + static struct pci_device_id esb2rom_pci_tbl[] __devinitdata = { 386 + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, 387 + PCI_ANY_ID, PCI_ANY_ID, }, 388 + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, 389 + PCI_ANY_ID, PCI_ANY_ID, }, 390 + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0, 391 + PCI_ANY_ID, PCI_ANY_ID, }, 392 + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, 393 + PCI_ANY_ID, PCI_ANY_ID, }, 394 + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_1, 395 + PCI_ANY_ID, PCI_ANY_ID, }, 396 + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_0, 397 + PCI_ANY_ID, PCI_ANY_ID, }, 398 + { 0, }, 399 + }; 400 + 401 + #if 0 402 + MODULE_DEVICE_TABLE(pci, esb2rom_pci_tbl); 403 + 404 + static struct pci_driver esb2rom_driver = { 405 + .name = MOD_NAME, 406 + .id_table = esb2rom_pci_tbl, 407 + .probe = esb2rom_init_one, 408 + .remove = esb2rom_remove_one, 409 + }; 410 + #endif 411 + 412 + static int __init init_esb2rom(void) 413 + { 414 + struct pci_dev *pdev; 415 + struct pci_device_id *id; 416 + int retVal; 417 + 418 + pdev = NULL; 419 + for (id = esb2rom_pci_tbl; id->vendor; id++) { 420 + printk(KERN_DEBUG "device id = %x\n", id->device); 421 + pdev = pci_get_device(id->vendor, id->device, NULL); 422 + if (pdev) { 423 + printk(KERN_DEBUG "matched device = %x\n", id->device); 424 + break; 425 + } 426 + } 427 + if (pdev) { 428 + printk(KERN_DEBUG "matched device id %x\n", id->device); 429 + retVal = esb2rom_init_one(pdev, &esb2rom_pci_tbl[0]); 430 + pci_dev_put(pdev); 431 + printk(KERN_DEBUG "retVal = %d\n", retVal); 432 + return retVal; 433 + } 434 + return -ENXIO; 435 + #if 0 436 + return pci_register_driver(&esb2rom_driver); 437 + #endif 438 + } 439 + 440 + static void __exit cleanup_esb2rom(void) 441 + { 442 + esb2rom_remove_one(esb2rom_window.pdev); 443 + } 444 + 445 + module_init(init_esb2rom); 446 + module_exit(cleanup_esb2rom); 447 + 448 + MODULE_LICENSE("GPL"); 449 + MODULE_AUTHOR("Lew Glendenning <lglendenning@lnxi.com>"); 450 + MODULE_DESCRIPTION("MTD map driver for BIOS chips on the ESB2 southbridge");
+1 -3
drivers/mtd/maps/integrator-flash.c
··· 75 int err; 76 void __iomem *base; 77 78 - info = kmalloc(sizeof(struct armflash_info), GFP_KERNEL); 79 if (!info) { 80 err = -ENOMEM; 81 goto out; 82 } 83 - 84 - memset(info, 0, sizeof(struct armflash_info)); 85 86 info->plat = plat; 87 if (plat && plat->init) {
··· 75 int err; 76 void __iomem *base; 77 78 + info = kzalloc(sizeof(struct armflash_info), GFP_KERNEL); 79 if (!info) { 80 err = -ENOMEM; 81 goto out; 82 } 83 84 info->plat = plat; 85 if (plat && plat->init) {
+3 -2
drivers/mtd/maps/nettel.c
··· 20 #include <linux/mtd/partitions.h> 21 #include <linux/mtd/cfi.h> 22 #include <linux/reboot.h> 23 #include <linux/kdev_t.h> 24 #include <linux/root_dev.h> 25 #include <asm/io.h> ··· 179 180 init_waitqueue_head(&wait_q); 181 mtd = get_mtd_device(NULL, 2); 182 - if (mtd) { 183 nettel_erase.mtd = mtd; 184 nettel_erase.callback = nettel_erasecallback; 185 nettel_erase.callback = NULL; ··· 472 iounmap(nettel_amd_map.virt); 473 474 return(rc); 475 - 476 } 477 478 /****************************************************************************/
··· 20 #include <linux/mtd/partitions.h> 21 #include <linux/mtd/cfi.h> 22 #include <linux/reboot.h> 23 + #include <linux/err.h> 24 #include <linux/kdev_t.h> 25 #include <linux/root_dev.h> 26 #include <asm/io.h> ··· 178 179 init_waitqueue_head(&wait_q); 180 mtd = get_mtd_device(NULL, 2); 181 + if (!IS_ERR(mtd)) { 182 nettel_erase.mtd = mtd; 183 nettel_erase.callback = nettel_erasecallback; 184 nettel_erase.callback = NULL; ··· 471 iounmap(nettel_amd_map.virt); 472 473 return(rc); 474 + 475 } 476 477 /****************************************************************************/
+1 -3
drivers/mtd/maps/omap_nor.c
··· 78 struct resource *res = pdev->resource; 79 unsigned long size = res->end - res->start + 1; 80 81 - info = kmalloc(sizeof(struct omapflash_info), GFP_KERNEL); 82 if (!info) 83 return -ENOMEM; 84 - 85 - memset(info, 0, sizeof(struct omapflash_info)); 86 87 if (!request_mem_region(res->start, size, "flash")) { 88 err = -EBUSY;
··· 78 struct resource *res = pdev->resource; 79 unsigned long size = res->end - res->start + 1; 80 81 + info = kzalloc(sizeof(struct omapflash_info), GFP_KERNEL); 82 if (!info) 83 return -ENOMEM; 84 85 if (!request_mem_region(res->start, size, "flash")) { 86 err = -EBUSY;
+1 -2
drivers/mtd/maps/pcmciamtd.c
··· 735 struct pcmciamtd_dev *dev; 736 737 /* Create new memory card device */ 738 - dev = kmalloc(sizeof(*dev), GFP_KERNEL); 739 if (!dev) return -ENOMEM; 740 DEBUG(1, "dev=0x%p", dev); 741 742 - memset(dev, 0, sizeof(*dev)); 743 dev->p_dev = link; 744 link->priv = dev; 745
··· 735 struct pcmciamtd_dev *dev; 736 737 /* Create new memory card device */ 738 + dev = kzalloc(sizeof(*dev), GFP_KERNEL); 739 if (!dev) return -ENOMEM; 740 DEBUG(1, "dev=0x%p", dev); 741 742 dev->p_dev = link; 743 link->priv = dev; 744
+2 -3
drivers/mtd/maps/physmap.c
··· 89 return -ENODEV; 90 91 printk(KERN_NOTICE "physmap platform flash device: %.8llx at %.8llx\n", 92 - (unsigned long long)dev->resource->end - dev->resource->start + 1, 93 (unsigned long long)dev->resource->start); 94 95 - info = kmalloc(sizeof(struct physmap_flash_info), GFP_KERNEL); 96 if (info == NULL) { 97 err = -ENOMEM; 98 goto err_out; 99 } 100 - memset(info, 0, sizeof(*info)); 101 102 platform_set_drvdata(dev, info); 103
··· 89 return -ENODEV; 90 91 printk(KERN_NOTICE "physmap platform flash device: %.8llx at %.8llx\n", 92 + (unsigned long long)(dev->resource->end - dev->resource->start + 1), 93 (unsigned long long)dev->resource->start); 94 95 + info = kzalloc(sizeof(struct physmap_flash_info), GFP_KERNEL); 96 if (info == NULL) { 97 err = -ENOMEM; 98 goto err_out; 99 } 100 101 platform_set_drvdata(dev, info); 102
+255
drivers/mtd/maps/physmap_of.c
···
··· 1 + /* 2 + * Normal mappings of chips in physical memory for OF devices 3 + * 4 + * Copyright (C) 2006 MontaVista Software Inc. 5 + * Author: Vitaly Wool <vwool@ru.mvista.com> 6 + * 7 + * This program is free software; you can redistribute it and/or modify it 8 + * under the terms of the GNU General Public License as published by the 9 + * Free Software Foundation; either version 2 of the License, or (at your 10 + * option) any later version. 11 + */ 12 + 13 + #include <linux/module.h> 14 + #include <linux/types.h> 15 + #include <linux/kernel.h> 16 + #include <linux/init.h> 17 + #include <linux/slab.h> 18 + #include <linux/device.h> 19 + #include <linux/mtd/mtd.h> 20 + #include <linux/mtd/map.h> 21 + #include <linux/mtd/partitions.h> 22 + #include <linux/mtd/physmap.h> 23 + #include <asm/io.h> 24 + #include <asm/prom.h> 25 + #include <asm/of_device.h> 26 + #include <asm/of_platform.h> 27 + 28 + struct physmap_flash_info { 29 + struct mtd_info *mtd; 30 + struct map_info map; 31 + struct resource *res; 32 + #ifdef CONFIG_MTD_PARTITIONS 33 + int nr_parts; 34 + struct mtd_partition *parts; 35 + #endif 36 + }; 37 + 38 + static const char *rom_probe_types[] = { "cfi_probe", "jedec_probe", "map_rom", NULL }; 39 + #ifdef CONFIG_MTD_PARTITIONS 40 + static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", NULL }; 41 + #endif 42 + 43 + #ifdef CONFIG_MTD_PARTITIONS 44 + static int parse_flash_partitions(struct device_node *node, 45 + struct mtd_partition **parts) 46 + { 47 + int i, plen, retval = -ENOMEM; 48 + const u32 *part; 49 + const char *name; 50 + 51 + part = get_property(node, "partitions", &plen); 52 + if (part == NULL) 53 + goto err; 54 + 55 + retval = plen / (2 * sizeof(u32)); 56 + *parts = kzalloc(retval * sizeof(struct mtd_partition), GFP_KERNEL); 57 + if (*parts == NULL) { 58 + printk(KERN_ERR "Can't allocate the flash partition data!\n"); 59 + goto err; 60 + } 61 + 62 + name = get_property(node, "partition-names", &plen); 63 + 64 + for (i = 0; i < retval; i++) { 65 + (*parts)[i].offset = *part++; 66 + (*parts)[i].size = *part & ~1; 67 + if (*part++ & 1) /* bit 0 set signifies read only partition */ 68 + (*parts)[i].mask_flags = MTD_WRITEABLE; 69 + 70 + if (name != NULL && plen > 0) { 71 + int len = strlen(name) + 1; 72 + 73 + (*parts)[i].name = (char *)name; 74 + plen -= len; 75 + name += len; 76 + } else 77 + (*parts)[i].name = "unnamed"; 78 + } 79 + err: 80 + return retval; 81 + } 82 + #endif 83 + 84 + static int of_physmap_remove(struct of_device *dev) 85 + { 86 + struct physmap_flash_info *info; 87 + 88 + info = dev_get_drvdata(&dev->dev); 89 + if (info == NULL) 90 + return 0; 91 + dev_set_drvdata(&dev->dev, NULL); 92 + 93 + if (info->mtd != NULL) { 94 + #ifdef CONFIG_MTD_PARTITIONS 95 + if (info->nr_parts) { 96 + del_mtd_partitions(info->mtd); 97 + kfree(info->parts); 98 + } else { 99 + del_mtd_device(info->mtd); 100 + } 101 + #else 102 + del_mtd_device(info->mtd); 103 + #endif 104 + map_destroy(info->mtd); 105 + } 106 + 107 + if (info->map.virt != NULL) 108 + iounmap(info->map.virt); 109 + 110 + if (info->res != NULL) { 111 + release_resource(info->res); 112 + kfree(info->res); 113 + } 114 + 115 + return 0; 116 + } 117 + 118 + static int __devinit of_physmap_probe(struct of_device *dev, const struct of_device_id *match) 119 + { 120 + struct device_node *dp = dev->node; 121 + struct resource res; 122 + struct physmap_flash_info *info; 123 + const char **probe_type; 124 + const char *of_probe; 125 + const u32 *width; 126 + int err; 127 + 128 + 129 + if (of_address_to_resource(dp, 0, &res)) { 130 + dev_err(&dev->dev, "Can't get the flash mapping!\n"); 131 + err = -EINVAL; 132 + goto err_out; 133 + } 134 + 135 + dev_dbg(&dev->dev, "physmap flash device: %.8llx at %.8llx\n", 136 + (unsigned long long)res.end - res.start + 1, 137 + (unsigned long long)res.start); 138 + 139 + info = kzalloc(sizeof(struct physmap_flash_info), GFP_KERNEL); 140 + if (info == NULL) { 141 + err = -ENOMEM; 142 + goto err_out; 143 + } 144 + memset(info, 0, sizeof(*info)); 145 + 146 + dev_set_drvdata(&dev->dev, info); 147 + 148 + info->res = request_mem_region(res.start, res.end - res.start + 1, 149 + dev->dev.bus_id); 150 + if (info->res == NULL) { 151 + dev_err(&dev->dev, "Could not reserve memory region\n"); 152 + err = -ENOMEM; 153 + goto err_out; 154 + } 155 + 156 + width = get_property(dp, "bank-width", NULL); 157 + if (width == NULL) { 158 + dev_err(&dev->dev, "Can't get the flash bank width!\n"); 159 + err = -EINVAL; 160 + goto err_out; 161 + } 162 + 163 + info->map.name = dev->dev.bus_id; 164 + info->map.phys = res.start; 165 + info->map.size = res.end - res.start + 1; 166 + info->map.bankwidth = *width; 167 + 168 + info->map.virt = ioremap(info->map.phys, info->map.size); 169 + if (info->map.virt == NULL) { 170 + dev_err(&dev->dev, "Failed to ioremap flash region\n"); 171 + err = EIO; 172 + goto err_out; 173 + } 174 + 175 + simple_map_init(&info->map); 176 + 177 + of_probe = get_property(dp, "probe-type", NULL); 178 + if (of_probe == NULL) { 179 + probe_type = rom_probe_types; 180 + for (; info->mtd == NULL && *probe_type != NULL; probe_type++) 181 + info->mtd = do_map_probe(*probe_type, &info->map); 182 + } else if (!strcmp(of_probe, "CFI")) 183 + info->mtd = do_map_probe("cfi_probe", &info->map); 184 + else if (!strcmp(of_probe, "JEDEC")) 185 + info->mtd = do_map_probe("jedec_probe", &info->map); 186 + else { 187 + if (strcmp(of_probe, "ROM")) 188 + dev_dbg(&dev->dev, "map_probe: don't know probe type " 189 + "'%s', mapping as rom\n"); 190 + info->mtd = do_map_probe("mtd_rom", &info->map); 191 + } 192 + if (info->mtd == NULL) { 193 + dev_err(&dev->dev, "map_probe failed\n"); 194 + err = -ENXIO; 195 + goto err_out; 196 + } 197 + info->mtd->owner = THIS_MODULE; 198 + 199 + #ifdef CONFIG_MTD_PARTITIONS 200 + err = parse_mtd_partitions(info->mtd, part_probe_types, &info->parts, 0); 201 + if (err > 0) { 202 + add_mtd_partitions(info->mtd, info->parts, err); 203 + } else if ((err = parse_flash_partitions(dp, &info->parts)) > 0) { 204 + dev_info(&dev->dev, "Using OF partition information\n"); 205 + add_mtd_partitions(info->mtd, info->parts, err); 206 + info->nr_parts = err; 207 + } else 208 + #endif 209 + 210 + add_mtd_device(info->mtd); 211 + return 0; 212 + 213 + err_out: 214 + of_physmap_remove(dev); 215 + return err; 216 + 217 + return 0; 218 + 219 + 220 + } 221 + 222 + static struct of_device_id of_physmap_match[] = { 223 + { 224 + .type = "rom", 225 + .compatible = "direct-mapped" 226 + }, 227 + { }, 228 + }; 229 + 230 + MODULE_DEVICE_TABLE(of, of_physmap_match); 231 + 232 + 233 + static struct of_platform_driver of_physmap_flash_driver = { 234 + .name = "physmap-flash", 235 + .match_table = of_physmap_match, 236 + .probe = of_physmap_probe, 237 + .remove = of_physmap_remove, 238 + }; 239 + 240 + static int __init of_physmap_init(void) 241 + { 242 + return of_register_platform_driver(&of_physmap_flash_driver); 243 + } 244 + 245 + static void __exit of_physmap_exit(void) 246 + { 247 + of_unregister_platform_driver(&of_physmap_flash_driver); 248 + } 249 + 250 + module_init(of_physmap_init); 251 + module_exit(of_physmap_exit); 252 + 253 + MODULE_LICENSE("GPL"); 254 + MODULE_AUTHOR("Vitaly Wool <vwool@ru.mvista.com>"); 255 + MODULE_DESCRIPTION("Configurable MTD map driver for OF");
+1 -2
drivers/mtd/maps/plat-ram.c
··· 147 148 pdata = pdev->dev.platform_data; 149 150 - info = kmalloc(sizeof(*info), GFP_KERNEL); 151 if (info == NULL) { 152 dev_err(&pdev->dev, "no memory for flash info\n"); 153 err = -ENOMEM; 154 goto exit_error; 155 } 156 157 - memset(info, 0, sizeof(*info)); 158 platform_set_drvdata(pdev, info); 159 160 info->dev = &pdev->dev;
··· 147 148 pdata = pdev->dev.platform_data; 149 150 + info = kzalloc(sizeof(*info), GFP_KERNEL); 151 if (info == NULL) { 152 dev_err(&pdev->dev, "no memory for flash info\n"); 153 err = -ENOMEM; 154 goto exit_error; 155 } 156 157 platform_set_drvdata(pdev, info); 158 159 info->dev = &pdev->dev;
+1 -3
drivers/mtd/maps/sa1100-flash.c
··· 273 /* 274 * Allocate the map_info structs in one go. 275 */ 276 - info = kmalloc(size, GFP_KERNEL); 277 if (!info) { 278 ret = -ENOMEM; 279 goto out; 280 } 281 - 282 - memset(info, 0, size); 283 284 if (plat->init) { 285 ret = plat->init();
··· 273 /* 274 * Allocate the map_info structs in one go. 275 */ 276 + info = kzalloc(size, GFP_KERNEL); 277 if (!info) { 278 ret = -ENOMEM; 279 goto out; 280 } 281 282 if (plat->init) { 283 ret = plat->init();
+2 -6
drivers/mtd/maps/tqm834x.c
··· 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;
··· 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;
+1 -2
drivers/mtd/maps/tqm8xxl.c
··· 134 135 printk(KERN_INFO "%s: chip probing count %d\n", __FUNCTION__, idx); 136 137 - map_banks[idx] = (struct map_info *)kmalloc(sizeof(struct map_info), GFP_KERNEL); 138 if(map_banks[idx] == NULL) { 139 ret = -ENOMEM; 140 /* FIXME: What if some MTD devices were probed already? */ 141 goto error_mem; 142 } 143 144 - memset((void *)map_banks[idx], 0, sizeof(struct map_info)); 145 map_banks[idx]->name = (char *)kmalloc(16, GFP_KERNEL); 146 147 if (!map_banks[idx]->name) {
··· 134 135 printk(KERN_INFO "%s: chip probing count %d\n", __FUNCTION__, idx); 136 137 + map_banks[idx] = kzalloc(sizeof(struct map_info), GFP_KERNEL); 138 if(map_banks[idx] == NULL) { 139 ret = -ENOMEM; 140 /* FIXME: What if some MTD devices were probed already? */ 141 goto error_mem; 142 } 143 144 map_banks[idx]->name = (char *)kmalloc(16, GFP_KERNEL); 145 146 if (!map_banks[idx]->name) {
+10 -9
drivers/mtd/mtd_blkdevs.c
··· 42 unsigned long block, nsect; 43 char *buf; 44 45 - block = req->sector; 46 - nsect = req->current_nr_sectors; 47 buf = req->buffer; 48 49 if (!blk_fs_request(req)) 50 return 0; 51 52 - if (block + nsect > get_capacity(req->rq_disk)) 53 return 0; 54 55 switch(rq_data_dir(req)) { 56 case READ: 57 - for (; nsect > 0; nsect--, block++, buf += 512) 58 if (tr->readsect(dev, block, buf)) 59 return 0; 60 return 1; ··· 64 if (!tr->writesect) 65 return 0; 66 67 - for (; nsect > 0; nsect--, block++, buf += 512) 68 if (tr->writesect(dev, block, buf)) 69 return 0; 70 return 1; ··· 298 299 /* 2.5 has capacity in units of 512 bytes while still 300 having BLOCK_SIZE_BITS set to 10. Just to keep us amused. */ 301 - set_capacity(gd, (new->size * new->blksize) >> 9); 302 303 gd->private_data = new; 304 new->blkcore_priv = gd; ··· 373 if (!blktrans_notifier.list.next) 374 register_mtd_user(&blktrans_notifier); 375 376 - tr->blkcore_priv = kmalloc(sizeof(*tr->blkcore_priv), GFP_KERNEL); 377 if (!tr->blkcore_priv) 378 return -ENOMEM; 379 - 380 - memset(tr->blkcore_priv, 0, sizeof(*tr->blkcore_priv)); 381 382 mutex_lock(&mtd_table_mutex); 383 ··· 400 } 401 402 tr->blkcore_priv->rq->queuedata = tr; 403 404 ret = kernel_thread(mtd_blktrans_thread, tr, CLONE_KERNEL); 405 if (ret < 0) {
··· 42 unsigned long block, nsect; 43 char *buf; 44 45 + block = req->sector << 9 >> tr->blkshift; 46 + nsect = req->current_nr_sectors << 9 >> tr->blkshift; 47 + 48 buf = req->buffer; 49 50 if (!blk_fs_request(req)) 51 return 0; 52 53 + if (req->sector + req->current_nr_sectors > get_capacity(req->rq_disk)) 54 return 0; 55 56 switch(rq_data_dir(req)) { 57 case READ: 58 + for (; nsect > 0; nsect--, block++, buf += tr->blksize) 59 if (tr->readsect(dev, block, buf)) 60 return 0; 61 return 1; ··· 63 if (!tr->writesect) 64 return 0; 65 66 + for (; nsect > 0; nsect--, block++, buf += tr->blksize) 67 if (tr->writesect(dev, block, buf)) 68 return 0; 69 return 1; ··· 297 298 /* 2.5 has capacity in units of 512 bytes while still 299 having BLOCK_SIZE_BITS set to 10. Just to keep us amused. */ 300 + set_capacity(gd, (new->size * tr->blksize) >> 9); 301 302 gd->private_data = new; 303 new->blkcore_priv = gd; ··· 372 if (!blktrans_notifier.list.next) 373 register_mtd_user(&blktrans_notifier); 374 375 + tr->blkcore_priv = kzalloc(sizeof(*tr->blkcore_priv), GFP_KERNEL); 376 if (!tr->blkcore_priv) 377 return -ENOMEM; 378 379 mutex_lock(&mtd_table_mutex); 380 ··· 401 } 402 403 tr->blkcore_priv->rq->queuedata = tr; 404 + blk_queue_hardsect_size(tr->blkcore_priv->rq, tr->blksize); 405 + tr->blkshift = ffs(tr->blksize) - 1; 406 407 ret = kernel_thread(mtd_blktrans_thread, tr, CLONE_KERNEL); 408 if (ret < 0) {
+4 -6
drivers/mtd/mtdblock.c
··· 278 } 279 280 /* OK, it's not open. Create cache info for it */ 281 - mtdblk = kmalloc(sizeof(struct mtdblk_dev), GFP_KERNEL); 282 if (!mtdblk) 283 return -ENOMEM; 284 285 - memset(mtdblk, 0, sizeof(*mtdblk)); 286 mtdblk->count = 1; 287 mtdblk->mtd = mtd; 288 ··· 338 339 static void mtdblock_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) 340 { 341 - struct mtd_blktrans_dev *dev = kmalloc(sizeof(*dev), GFP_KERNEL); 342 343 if (!dev) 344 return; 345 346 - memset(dev, 0, sizeof(*dev)); 347 - 348 dev->mtd = mtd; 349 dev->devnum = mtd->index; 350 - dev->blksize = 512; 351 dev->size = mtd->size >> 9; 352 dev->tr = tr; 353 ··· 365 .name = "mtdblock", 366 .major = 31, 367 .part_bits = 0, 368 .open = mtdblock_open, 369 .flush = mtdblock_flush, 370 .release = mtdblock_release,
··· 278 } 279 280 /* OK, it's not open. Create cache info for it */ 281 + mtdblk = kzalloc(sizeof(struct mtdblk_dev), GFP_KERNEL); 282 if (!mtdblk) 283 return -ENOMEM; 284 285 mtdblk->count = 1; 286 mtdblk->mtd = mtd; 287 ··· 339 340 static void mtdblock_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) 341 { 342 + struct mtd_blktrans_dev *dev = kzalloc(sizeof(*dev), GFP_KERNEL); 343 344 if (!dev) 345 return; 346 347 dev->mtd = mtd; 348 dev->devnum = mtd->index; 349 + 350 dev->size = mtd->size >> 9; 351 dev->tr = tr; 352 ··· 368 .name = "mtdblock", 369 .major = 31, 370 .part_bits = 0, 371 + .blksize = 512, 372 .open = mtdblock_open, 373 .flush = mtdblock_flush, 374 .release = mtdblock_release,
+3 -4
drivers/mtd/mtdblock_ro.c
··· 33 34 static void mtdblock_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) 35 { 36 - struct mtd_blktrans_dev *dev = kmalloc(sizeof(*dev), GFP_KERNEL); 37 38 if (!dev) 39 return; 40 41 - memset(dev, 0, sizeof(*dev)); 42 - 43 dev->mtd = mtd; 44 dev->devnum = mtd->index; 45 - dev->blksize = 512; 46 dev->size = mtd->size >> 9; 47 dev->tr = tr; 48 dev->readonly = 1; ··· 58 .name = "mtdblock", 59 .major = 31, 60 .part_bits = 0, 61 .readsect = mtdblock_readsect, 62 .writesect = mtdblock_writesect, 63 .add_mtd = mtdblock_add_mtd,
··· 33 34 static void mtdblock_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) 35 { 36 + struct mtd_blktrans_dev *dev = kzalloc(sizeof(*dev), GFP_KERNEL); 37 38 if (!dev) 39 return; 40 41 dev->mtd = mtd; 42 dev->devnum = mtd->index; 43 + 44 dev->size = mtd->size >> 9; 45 dev->tr = tr; 46 dev->readonly = 1; ··· 60 .name = "mtdblock", 61 .major = 31, 62 .part_bits = 0, 63 + .blksize = 512, 64 .readsect = mtdblock_readsect, 65 .writesect = mtdblock_writesect, 66 .add_mtd = mtdblock_add_mtd,
+11 -12
drivers/mtd/mtdchar.c
··· 7 8 #include <linux/device.h> 9 #include <linux/fs.h> 10 #include <linux/init.h> 11 #include <linux/kernel.h> 12 #include <linux/module.h> ··· 101 102 mtd = get_mtd_device(NULL, devnum); 103 104 - if (!mtd) 105 - return -ENODEV; 106 107 if (MTD_ABSENT == mtd->type) { 108 put_mtd_device(mtd); ··· 432 if(!(file->f_mode & 2)) 433 return -EPERM; 434 435 - erase=kmalloc(sizeof(struct erase_info),GFP_KERNEL); 436 if (!erase) 437 ret = -ENOMEM; 438 else { ··· 441 442 init_waitqueue_head(&waitq); 443 444 - memset (erase,0,sizeof(struct erase_info)); 445 if (copy_from_user(&erase->addr, argp, 446 sizeof(struct erase_info_user))) { 447 kfree(erase); ··· 499 if (ret) 500 return ret; 501 502 - ops.len = buf.length; 503 ops.ooblen = buf.length; 504 ops.ooboffs = buf.start & (mtd->oobsize - 1); 505 ops.datbuf = NULL; 506 ops.mode = MTD_OOB_PLACE; 507 508 - if (ops.ooboffs && ops.len > (mtd->oobsize - ops.ooboffs)) 509 return -EINVAL; 510 511 ops.oobbuf = kmalloc(buf.length, GFP_KERNEL); ··· 519 buf.start &= ~(mtd->oobsize - 1); 520 ret = mtd->write_oob(mtd, buf.start, &ops); 521 522 - if (copy_to_user(argp + sizeof(uint32_t), &ops.retlen, 523 sizeof(uint32_t))) 524 ret = -EFAULT; 525 ··· 547 if (ret) 548 return ret; 549 550 - ops.len = buf.length; 551 ops.ooblen = buf.length; 552 ops.ooboffs = buf.start & (mtd->oobsize - 1); 553 ops.datbuf = NULL; ··· 562 buf.start &= ~(mtd->oobsize - 1); 563 ret = mtd->read_oob(mtd, buf.start, &ops); 564 565 - if (put_user(ops.retlen, (uint32_t __user *)argp)) 566 ret = -EFAULT; 567 - else if (ops.retlen && copy_to_user(buf.ptr, ops.oobbuf, 568 - ops.retlen)) 569 ret = -EFAULT; 570 571 kfree(ops.oobbuf); ··· 614 memcpy(&oi.eccpos, mtd->ecclayout->eccpos, sizeof(oi.eccpos)); 615 memcpy(&oi.oobfree, mtd->ecclayout->oobfree, 616 sizeof(oi.oobfree)); 617 618 if (copy_to_user(argp, &oi, sizeof(struct nand_oobinfo))) 619 return -EFAULT; ··· 714 if (!mtd->ecclayout) 715 return -EOPNOTSUPP; 716 717 - if (copy_to_user(argp, &mtd->ecclayout, 718 sizeof(struct nand_ecclayout))) 719 return -EFAULT; 720 break;
··· 7 8 #include <linux/device.h> 9 #include <linux/fs.h> 10 + #include <linux/err.h> 11 #include <linux/init.h> 12 #include <linux/kernel.h> 13 #include <linux/module.h> ··· 100 101 mtd = get_mtd_device(NULL, devnum); 102 103 + if (IS_ERR(mtd)) 104 + return PTR_ERR(mtd); 105 106 if (MTD_ABSENT == mtd->type) { 107 put_mtd_device(mtd); ··· 431 if(!(file->f_mode & 2)) 432 return -EPERM; 433 434 + erase=kzalloc(sizeof(struct erase_info),GFP_KERNEL); 435 if (!erase) 436 ret = -ENOMEM; 437 else { ··· 440 441 init_waitqueue_head(&waitq); 442 443 if (copy_from_user(&erase->addr, argp, 444 sizeof(struct erase_info_user))) { 445 kfree(erase); ··· 499 if (ret) 500 return ret; 501 502 ops.ooblen = buf.length; 503 ops.ooboffs = buf.start & (mtd->oobsize - 1); 504 ops.datbuf = NULL; 505 ops.mode = MTD_OOB_PLACE; 506 507 + if (ops.ooboffs && ops.ooblen > (mtd->oobsize - ops.ooboffs)) 508 return -EINVAL; 509 510 ops.oobbuf = kmalloc(buf.length, GFP_KERNEL); ··· 520 buf.start &= ~(mtd->oobsize - 1); 521 ret = mtd->write_oob(mtd, buf.start, &ops); 522 523 + if (copy_to_user(argp + sizeof(uint32_t), &ops.oobretlen, 524 sizeof(uint32_t))) 525 ret = -EFAULT; 526 ··· 548 if (ret) 549 return ret; 550 551 ops.ooblen = buf.length; 552 ops.ooboffs = buf.start & (mtd->oobsize - 1); 553 ops.datbuf = NULL; ··· 564 buf.start &= ~(mtd->oobsize - 1); 565 ret = mtd->read_oob(mtd, buf.start, &ops); 566 567 + if (put_user(ops.oobretlen, (uint32_t __user *)argp)) 568 ret = -EFAULT; 569 + else if (ops.oobretlen && copy_to_user(buf.ptr, ops.oobbuf, 570 + ops.oobretlen)) 571 ret = -EFAULT; 572 573 kfree(ops.oobbuf); ··· 616 memcpy(&oi.eccpos, mtd->ecclayout->eccpos, sizeof(oi.eccpos)); 617 memcpy(&oi.oobfree, mtd->ecclayout->oobfree, 618 sizeof(oi.oobfree)); 619 + oi.eccbytes = mtd->ecclayout->eccbytes; 620 621 if (copy_to_user(argp, &oi, sizeof(struct nand_oobinfo))) 622 return -EFAULT; ··· 715 if (!mtd->ecclayout) 716 return -EOPNOTSUPP; 717 718 + if (copy_to_user(argp, mtd->ecclayout, 719 sizeof(struct nand_ecclayout))) 720 return -EFAULT; 721 break;
+26 -17
drivers/mtd/mtdconcat.c
··· 247 struct mtd_oob_ops devops = *ops; 248 int i, err, ret = 0; 249 250 - ops->retlen = 0; 251 252 for (i = 0; i < concat->num_subdev; i++) { 253 struct mtd_info *subdev = concat->subdev[i]; ··· 263 264 err = subdev->read_oob(subdev, from, &devops); 265 ops->retlen += devops.retlen; 266 267 /* Save information about bitflips! */ 268 if (unlikely(err)) { ··· 279 return err; 280 } 281 282 - devops.len = ops->len - ops->retlen; 283 - if (!devops.len) 284 - return ret; 285 - 286 - if (devops.datbuf) 287 devops.datbuf += devops.retlen; 288 - if (devops.oobbuf) 289 - devops.oobbuf += devops.ooblen; 290 291 from = 0; 292 } ··· 326 if (err) 327 return err; 328 329 - devops.len = ops->len - ops->retlen; 330 - if (!devops.len) 331 - return 0; 332 - 333 - if (devops.datbuf) 334 devops.datbuf += devops.retlen; 335 - if (devops.oobbuf) 336 - devops.oobbuf += devops.ooblen; 337 to = 0; 338 } 339 return -EINVAL; ··· 708 709 /* allocate the device structure */ 710 size = SIZEOF_STRUCT_MTD_CONCAT(num_devs); 711 - concat = kmalloc(size, GFP_KERNEL); 712 if (!concat) { 713 printk 714 ("memory allocation error while creating concatenated device \"%s\"\n", 715 name); 716 return NULL; 717 } 718 - memset(concat, 0, size); 719 concat->subdev = (struct mtd_info **) (concat + 1); 720 721 /* ··· 772 concat->mtd.ecc_stats.badblocks += 773 subdev[i]->ecc_stats.badblocks; 774 if (concat->mtd.writesize != subdev[i]->writesize || 775 concat->mtd.oobsize != subdev[i]->oobsize || 776 concat->mtd.ecctype != subdev[i]->ecctype || 777 concat->mtd.eccsize != subdev[i]->eccsize ||
··· 247 struct mtd_oob_ops devops = *ops; 248 int i, err, ret = 0; 249 250 + ops->retlen = ops->oobretlen = 0; 251 252 for (i = 0; i < concat->num_subdev; i++) { 253 struct mtd_info *subdev = concat->subdev[i]; ··· 263 264 err = subdev->read_oob(subdev, from, &devops); 265 ops->retlen += devops.retlen; 266 + ops->oobretlen += devops.oobretlen; 267 268 /* Save information about bitflips! */ 269 if (unlikely(err)) { ··· 278 return err; 279 } 280 281 + if (devops.datbuf) { 282 + devops.len = ops->len - ops->retlen; 283 + if (!devops.len) 284 + return ret; 285 devops.datbuf += devops.retlen; 286 + } 287 + if (devops.oobbuf) { 288 + devops.ooblen = ops->ooblen - ops->oobretlen; 289 + if (!devops.ooblen) 290 + return ret; 291 + devops.oobbuf += ops->oobretlen; 292 + } 293 294 from = 0; 295 } ··· 321 if (err) 322 return err; 323 324 + if (devops.datbuf) { 325 + devops.len = ops->len - ops->retlen; 326 + if (!devops.len) 327 + return 0; 328 devops.datbuf += devops.retlen; 329 + } 330 + if (devops.oobbuf) { 331 + devops.ooblen = ops->ooblen - ops->oobretlen; 332 + if (!devops.ooblen) 333 + return 0; 334 + devops.oobbuf += devops.oobretlen; 335 + } 336 to = 0; 337 } 338 return -EINVAL; ··· 699 700 /* allocate the device structure */ 701 size = SIZEOF_STRUCT_MTD_CONCAT(num_devs); 702 + concat = kzalloc(size, GFP_KERNEL); 703 if (!concat) { 704 printk 705 ("memory allocation error while creating concatenated device \"%s\"\n", 706 name); 707 return NULL; 708 } 709 concat->subdev = (struct mtd_info **) (concat + 1); 710 711 /* ··· 764 concat->mtd.ecc_stats.badblocks += 765 subdev[i]->ecc_stats.badblocks; 766 if (concat->mtd.writesize != subdev[i]->writesize || 767 + concat->mtd.subpage_sft != subdev[i]->subpage_sft || 768 concat->mtd.oobsize != subdev[i]->oobsize || 769 concat->mtd.ecctype != subdev[i]->ecctype || 770 concat->mtd.eccsize != subdev[i]->eccsize ||
+78 -15
drivers/mtd/mtdcore.c
··· 15 #include <linux/timer.h> 16 #include <linux/major.h> 17 #include <linux/fs.h> 18 #include <linux/ioctl.h> 19 #include <linux/init.h> 20 #include <linux/mtd/compatmac.h> ··· 193 * Given a number and NULL address, return the num'th entry in the device 194 * table, if any. Given an address and num == -1, search the device table 195 * for a device with that address and return if it's still present. Given 196 - * both, return the num'th driver only if its address matches. Return NULL 197 - * if not. 198 */ 199 200 struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num) 201 { 202 struct mtd_info *ret = NULL; 203 - int i; 204 205 mutex_lock(&mtd_table_mutex); 206 ··· 214 ret = NULL; 215 } 216 217 - if (ret && !try_module_get(ret->owner)) 218 - ret = NULL; 219 220 - if (ret) 221 - ret->usecount++; 222 223 mutex_unlock(&mtd_table_mutex); 224 return ret; 225 } 226 227 void put_mtd_device(struct mtd_info *mtd) ··· 289 290 mutex_lock(&mtd_table_mutex); 291 c = --mtd->usecount; 292 mutex_unlock(&mtd_table_mutex); 293 BUG_ON(c < 0); 294 ··· 298 } 299 300 /* default_mtd_writev - default mtd writev method for MTD devices that 301 - * dont implement their own 302 */ 303 304 int default_mtd_writev(struct mtd_info *mtd, const struct kvec *vecs, ··· 326 return ret; 327 } 328 329 - EXPORT_SYMBOL(add_mtd_device); 330 - EXPORT_SYMBOL(del_mtd_device); 331 - EXPORT_SYMBOL(get_mtd_device); 332 - EXPORT_SYMBOL(put_mtd_device); 333 - EXPORT_SYMBOL(register_mtd_user); 334 - EXPORT_SYMBOL(unregister_mtd_user); 335 - EXPORT_SYMBOL(default_mtd_writev); 336 337 #ifdef CONFIG_PROC_FS 338
··· 15 #include <linux/timer.h> 16 #include <linux/major.h> 17 #include <linux/fs.h> 18 + #include <linux/err.h> 19 #include <linux/ioctl.h> 20 #include <linux/init.h> 21 #include <linux/mtd/compatmac.h> ··· 192 * Given a number and NULL address, return the num'th entry in the device 193 * table, if any. Given an address and num == -1, search the device table 194 * for a device with that address and return if it's still present. Given 195 + * both, return the num'th driver only if its address matches. Return 196 + * error code if not. 197 */ 198 199 struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num) 200 { 201 struct mtd_info *ret = NULL; 202 + int i, err = -ENODEV; 203 204 mutex_lock(&mtd_table_mutex); 205 ··· 213 ret = NULL; 214 } 215 216 + if (!ret) 217 + goto out_unlock; 218 219 + if (!try_module_get(ret->owner)) 220 + goto out_unlock; 221 222 + if (ret->get_device) { 223 + err = ret->get_device(ret); 224 + if (err) 225 + goto out_put; 226 + } 227 + 228 + ret->usecount++; 229 mutex_unlock(&mtd_table_mutex); 230 return ret; 231 + 232 + out_put: 233 + module_put(ret->owner); 234 + out_unlock: 235 + mutex_unlock(&mtd_table_mutex); 236 + return ERR_PTR(err); 237 + } 238 + 239 + /** 240 + * get_mtd_device_nm - obtain a validated handle for an MTD device by 241 + * device name 242 + * @name: MTD device name to open 243 + * 244 + * This function returns MTD device description structure in case of 245 + * success and an error code in case of failure. 246 + */ 247 + 248 + struct mtd_info *get_mtd_device_nm(const char *name) 249 + { 250 + int i, err = -ENODEV; 251 + struct mtd_info *mtd = NULL; 252 + 253 + mutex_lock(&mtd_table_mutex); 254 + 255 + for (i = 0; i < MAX_MTD_DEVICES; i++) { 256 + if (mtd_table[i] && !strcmp(name, mtd_table[i]->name)) { 257 + mtd = mtd_table[i]; 258 + break; 259 + } 260 + } 261 + 262 + if (!mtd) 263 + goto out_unlock; 264 + 265 + if (!try_module_get(mtd->owner)) 266 + goto out_unlock; 267 + 268 + if (mtd->get_device) { 269 + err = mtd->get_device(mtd); 270 + if (err) 271 + goto out_put; 272 + } 273 + 274 + mtd->usecount++; 275 + mutex_unlock(&mtd_table_mutex); 276 + return mtd; 277 + 278 + out_put: 279 + module_put(mtd->owner); 280 + out_unlock: 281 + mutex_unlock(&mtd_table_mutex); 282 + return ERR_PTR(err); 283 } 284 285 void put_mtd_device(struct mtd_info *mtd) ··· 229 230 mutex_lock(&mtd_table_mutex); 231 c = --mtd->usecount; 232 + if (mtd->put_device) 233 + mtd->put_device(mtd); 234 mutex_unlock(&mtd_table_mutex); 235 BUG_ON(c < 0); 236 ··· 236 } 237 238 /* default_mtd_writev - default mtd writev method for MTD devices that 239 + * don't implement their own 240 */ 241 242 int default_mtd_writev(struct mtd_info *mtd, const struct kvec *vecs, ··· 264 return ret; 265 } 266 267 + EXPORT_SYMBOL_GPL(add_mtd_device); 268 + EXPORT_SYMBOL_GPL(del_mtd_device); 269 + EXPORT_SYMBOL_GPL(get_mtd_device); 270 + EXPORT_SYMBOL_GPL(get_mtd_device_nm); 271 + EXPORT_SYMBOL_GPL(put_mtd_device); 272 + EXPORT_SYMBOL_GPL(register_mtd_user); 273 + EXPORT_SYMBOL_GPL(unregister_mtd_user); 274 + EXPORT_SYMBOL_GPL(default_mtd_writev); 275 276 #ifdef CONFIG_PROC_FS 277
+4 -4
drivers/mtd/mtdpart.c
··· 94 95 if (from >= mtd->size) 96 return -EINVAL; 97 - if (from + ops->len > mtd->size) 98 return -EINVAL; 99 res = part->master->read_oob(part->master, from + part->offset, ops); 100 ··· 161 162 if (to >= mtd->size) 163 return -EINVAL; 164 - if (to + ops->len > mtd->size) 165 return -EINVAL; 166 return part->master->write_oob(part->master, to + part->offset, ops); 167 } ··· 323 for (i = 0; i < nbparts; i++) { 324 325 /* allocate the partition structure */ 326 - slave = kmalloc (sizeof(*slave), GFP_KERNEL); 327 if (!slave) { 328 printk ("memory allocation error while creating partitions for \"%s\"\n", 329 master->name); 330 del_mtd_partitions(master); 331 return -ENOMEM; 332 } 333 - memset(slave, 0, sizeof(*slave)); 334 list_add(&slave->list, &mtd_partitions); 335 336 /* set up the MTD object for this partition */ ··· 340 slave->mtd.oobsize = master->oobsize; 341 slave->mtd.ecctype = master->ecctype; 342 slave->mtd.eccsize = master->eccsize; 343 344 slave->mtd.name = parts[i].name; 345 slave->mtd.bank_size = master->bank_size;
··· 94 95 if (from >= mtd->size) 96 return -EINVAL; 97 + if (ops->datbuf && from + ops->len > mtd->size) 98 return -EINVAL; 99 res = part->master->read_oob(part->master, from + part->offset, ops); 100 ··· 161 162 if (to >= mtd->size) 163 return -EINVAL; 164 + if (ops->datbuf && to + ops->len > mtd->size) 165 return -EINVAL; 166 return part->master->write_oob(part->master, to + part->offset, ops); 167 } ··· 323 for (i = 0; i < nbparts; i++) { 324 325 /* allocate the partition structure */ 326 + slave = kzalloc (sizeof(*slave), GFP_KERNEL); 327 if (!slave) { 328 printk ("memory allocation error while creating partitions for \"%s\"\n", 329 master->name); 330 del_mtd_partitions(master); 331 return -ENOMEM; 332 } 333 list_add(&slave->list, &mtd_partitions); 334 335 /* set up the MTD object for this partition */ ··· 341 slave->mtd.oobsize = master->oobsize; 342 slave->mtd.ecctype = master->ecctype; 343 slave->mtd.eccsize = master->eccsize; 344 + slave->mtd.subpage_sft = master->subpage_sft; 345 346 slave->mtd.name = parts[i].name; 347 slave->mtd.bank_size = master->bank_size;
+16
drivers/mtd/nand/Kconfig
··· 90 depends on MTD_NAND && SH_SOLUTION_ENGINE 91 select REED_SOLOMON 92 select REED_SOLOMON_DEC8 93 help 94 This enables the driver for the Renesas Technology AG-AND 95 flash interface board (FROM_BOARD4) ··· 133 config MTD_NAND_NDFC 134 tristate "NDFC NanD Flash Controller" 135 depends on MTD_NAND && 44x 136 help 137 NDFC Nand Flash Controllers are integrated in EP44x SoCs 138 ··· 221 tristate "Support for NAND Flash on Sharp SL Series (C7xx + others)" 222 depends on MTD_NAND && ARCH_PXA 223 224 config MTD_NAND_CS553X 225 tristate "NAND support for CS5535/CS5536 (AMD Geode companion chip)" 226 depends on MTD_NAND && X86_32 && (X86_PC || X86_GENERICARCH) ··· 240 the controller be in MMIO mode. 241 242 If you say "m", the module will be called "cs553x_nand.ko". 243 244 config MTD_NAND_NANDSIM 245 tristate "Support for NAND Flash Simulator"
··· 90 depends on MTD_NAND && SH_SOLUTION_ENGINE 91 select REED_SOLOMON 92 select REED_SOLOMON_DEC8 93 + select BITREVERSE 94 help 95 This enables the driver for the Renesas Technology AG-AND 96 flash interface board (FROM_BOARD4) ··· 132 config MTD_NAND_NDFC 133 tristate "NDFC NanD Flash Controller" 134 depends on MTD_NAND && 44x 135 + select MTD_NAND_ECC_SMC 136 help 137 NDFC Nand Flash Controllers are integrated in EP44x SoCs 138 ··· 219 tristate "Support for NAND Flash on Sharp SL Series (C7xx + others)" 220 depends on MTD_NAND && ARCH_PXA 221 222 + config MTD_NAND_CAFE 223 + tristate "NAND support for OLPC CAFÉ chip" 224 + depends on PCI 225 + help 226 + Use NAND flash attached to the CAFÉ chip designed for the $100 227 + laptop. 228 + 229 config MTD_NAND_CS553X 230 tristate "NAND support for CS5535/CS5536 (AMD Geode companion chip)" 231 depends on MTD_NAND && X86_32 && (X86_PC || X86_GENERICARCH) ··· 231 the controller be in MMIO mode. 232 233 If you say "m", the module will be called "cs553x_nand.ko". 234 + 235 + config MTD_NAND_AT91 236 + bool "Support for NAND Flash / SmartMedia on AT91" 237 + depends on MTD_NAND && ARCH_AT91 238 + help 239 + Enables support for NAND Flash / Smart Media Card interface 240 + on Atmel AT91 processors. 241 242 config MTD_NAND_NANDSIM 243 tristate "Support for NAND Flash Simulator"
+4 -1
drivers/mtd/nand/Makefile
··· 6 obj-$(CONFIG_MTD_NAND) += nand.o nand_ecc.o 7 obj-$(CONFIG_MTD_NAND_IDS) += nand_ids.o 8 9 obj-$(CONFIG_MTD_NAND_SPIA) += spia.o 10 obj-$(CONFIG_MTD_NAND_AMS_DELTA) += ams-delta.o 11 obj-$(CONFIG_MTD_NAND_TOTO) += toto.o ··· 23 obj-$(CONFIG_MTD_NAND_NANDSIM) += nandsim.o 24 obj-$(CONFIG_MTD_NAND_CS553X) += cs553x_nand.o 25 obj-$(CONFIG_MTD_NAND_NDFC) += ndfc.o 26 27 - nand-objs = nand_base.o nand_bbt.o
··· 6 obj-$(CONFIG_MTD_NAND) += nand.o nand_ecc.o 7 obj-$(CONFIG_MTD_NAND_IDS) += nand_ids.o 8 9 + obj-$(CONFIG_MTD_NAND_CAFE) += cafe_nand.o 10 obj-$(CONFIG_MTD_NAND_SPIA) += spia.o 11 obj-$(CONFIG_MTD_NAND_AMS_DELTA) += ams-delta.o 12 obj-$(CONFIG_MTD_NAND_TOTO) += toto.o ··· 22 obj-$(CONFIG_MTD_NAND_NANDSIM) += nandsim.o 23 obj-$(CONFIG_MTD_NAND_CS553X) += cs553x_nand.o 24 obj-$(CONFIG_MTD_NAND_NDFC) += ndfc.o 25 + obj-$(CONFIG_MTD_NAND_AT91) += at91_nand.o 26 27 + nand-objs := nand_base.o nand_bbt.o 28 + cafe_nand-objs := cafe.o cafe_ecc.o
+223
drivers/mtd/nand/at91_nand.c
···
··· 1 + /* 2 + * drivers/mtd/nand/at91_nand.c 3 + * 4 + * Copyright (C) 2003 Rick Bronson 5 + * 6 + * Derived from drivers/mtd/nand/autcpu12.c 7 + * Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de) 8 + * 9 + * Derived from drivers/mtd/spia.c 10 + * Copyright (C) 2000 Steven J. Hill (sjhill@cotw.com) 11 + * 12 + * This program is free software; you can redistribute it and/or modify 13 + * it under the terms of the GNU General Public License version 2 as 14 + * published by the Free Software Foundation. 15 + * 16 + */ 17 + 18 + #include <linux/slab.h> 19 + #include <linux/module.h> 20 + #include <linux/platform_device.h> 21 + #include <linux/mtd/mtd.h> 22 + #include <linux/mtd/nand.h> 23 + #include <linux/mtd/partitions.h> 24 + 25 + #include <asm/io.h> 26 + #include <asm/sizes.h> 27 + 28 + #include <asm/hardware.h> 29 + #include <asm/arch/board.h> 30 + #include <asm/arch/gpio.h> 31 + 32 + struct at91_nand_host { 33 + struct nand_chip nand_chip; 34 + struct mtd_info mtd; 35 + void __iomem *io_base; 36 + struct at91_nand_data *board; 37 + }; 38 + 39 + /* 40 + * Hardware specific access to control-lines 41 + */ 42 + static void at91_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) 43 + { 44 + struct nand_chip *nand_chip = mtd->priv; 45 + struct at91_nand_host *host = nand_chip->priv; 46 + 47 + if (cmd == NAND_CMD_NONE) 48 + return; 49 + 50 + if (ctrl & NAND_CLE) 51 + writeb(cmd, host->io_base + (1 << host->board->cle)); 52 + else 53 + writeb(cmd, host->io_base + (1 << host->board->ale)); 54 + } 55 + 56 + /* 57 + * Read the Device Ready pin. 58 + */ 59 + static int at91_nand_device_ready(struct mtd_info *mtd) 60 + { 61 + struct nand_chip *nand_chip = mtd->priv; 62 + struct at91_nand_host *host = nand_chip->priv; 63 + 64 + return at91_get_gpio_value(host->board->rdy_pin); 65 + } 66 + 67 + /* 68 + * Enable NAND. 69 + */ 70 + static void at91_nand_enable(struct at91_nand_host *host) 71 + { 72 + if (host->board->enable_pin) 73 + at91_set_gpio_value(host->board->enable_pin, 0); 74 + } 75 + 76 + /* 77 + * Disable NAND. 78 + */ 79 + static void at91_nand_disable(struct at91_nand_host *host) 80 + { 81 + if (host->board->enable_pin) 82 + at91_set_gpio_value(host->board->enable_pin, 1); 83 + } 84 + 85 + /* 86 + * Probe for the NAND device. 87 + */ 88 + static int __init at91_nand_probe(struct platform_device *pdev) 89 + { 90 + struct at91_nand_host *host; 91 + struct mtd_info *mtd; 92 + struct nand_chip *nand_chip; 93 + int res; 94 + 95 + #ifdef CONFIG_MTD_PARTITIONS 96 + struct mtd_partition *partitions = NULL; 97 + int num_partitions = 0; 98 + #endif 99 + 100 + /* Allocate memory for the device structure (and zero it) */ 101 + host = kzalloc(sizeof(struct at91_nand_host), GFP_KERNEL); 102 + if (!host) { 103 + printk(KERN_ERR "at91_nand: failed to allocate device structure.\n"); 104 + return -ENOMEM; 105 + } 106 + 107 + host->io_base = ioremap(pdev->resource[0].start, 108 + pdev->resource[0].end - pdev->resource[0].start + 1); 109 + if (host->io_base == NULL) { 110 + printk(KERN_ERR "at91_nand: ioremap failed\n"); 111 + kfree(host); 112 + return -EIO; 113 + } 114 + 115 + mtd = &host->mtd; 116 + nand_chip = &host->nand_chip; 117 + host->board = pdev->dev.platform_data; 118 + 119 + nand_chip->priv = host; /* link the private data structures */ 120 + mtd->priv = nand_chip; 121 + mtd->owner = THIS_MODULE; 122 + 123 + /* Set address of NAND IO lines */ 124 + nand_chip->IO_ADDR_R = host->io_base; 125 + nand_chip->IO_ADDR_W = host->io_base; 126 + nand_chip->cmd_ctrl = at91_nand_cmd_ctrl; 127 + nand_chip->dev_ready = at91_nand_device_ready; 128 + nand_chip->ecc.mode = NAND_ECC_SOFT; /* enable ECC */ 129 + nand_chip->chip_delay = 20; /* 20us command delay time */ 130 + 131 + if (host->board->bus_width_16) /* 16-bit bus width */ 132 + nand_chip->options |= NAND_BUSWIDTH_16; 133 + 134 + platform_set_drvdata(pdev, host); 135 + at91_nand_enable(host); 136 + 137 + if (host->board->det_pin) { 138 + if (at91_get_gpio_value(host->board->det_pin)) { 139 + printk ("No SmartMedia card inserted.\n"); 140 + res = ENXIO; 141 + goto out; 142 + } 143 + } 144 + 145 + /* Scan to find existance of the device */ 146 + if (nand_scan(mtd, 1)) { 147 + res = -ENXIO; 148 + goto out; 149 + } 150 + 151 + #ifdef CONFIG_MTD_PARTITIONS 152 + if (host->board->partition_info) 153 + partitions = host->board->partition_info(mtd->size, &num_partitions); 154 + 155 + if ((!partitions) || (num_partitions == 0)) { 156 + printk(KERN_ERR "at91_nand: No parititions defined, or unsupported device.\n"); 157 + res = ENXIO; 158 + goto release; 159 + } 160 + 161 + res = add_mtd_partitions(mtd, partitions, num_partitions); 162 + #else 163 + res = add_mtd_device(mtd); 164 + #endif 165 + 166 + if (!res) 167 + return res; 168 + 169 + release: 170 + nand_release(mtd); 171 + out: 172 + at91_nand_disable(host); 173 + platform_set_drvdata(pdev, NULL); 174 + iounmap(host->io_base); 175 + kfree(host); 176 + return res; 177 + } 178 + 179 + /* 180 + * Remove a NAND device. 181 + */ 182 + static int __devexit at91_nand_remove(struct platform_device *pdev) 183 + { 184 + struct at91_nand_host *host = platform_get_drvdata(pdev); 185 + struct mtd_info *mtd = &host->mtd; 186 + 187 + nand_release(mtd); 188 + 189 + at91_nand_disable(host); 190 + 191 + iounmap(host->io_base); 192 + kfree(host); 193 + 194 + return 0; 195 + } 196 + 197 + static struct platform_driver at91_nand_driver = { 198 + .probe = at91_nand_probe, 199 + .remove = at91_nand_remove, 200 + .driver = { 201 + .name = "at91_nand", 202 + .owner = THIS_MODULE, 203 + }, 204 + }; 205 + 206 + static int __init at91_nand_init(void) 207 + { 208 + return platform_driver_register(&at91_nand_driver); 209 + } 210 + 211 + 212 + static void __exit at91_nand_exit(void) 213 + { 214 + platform_driver_unregister(&at91_nand_driver); 215 + } 216 + 217 + 218 + module_init(at91_nand_init); 219 + module_exit(at91_nand_exit); 220 + 221 + MODULE_LICENSE("GPL"); 222 + MODULE_AUTHOR("Rick Bronson"); 223 + MODULE_DESCRIPTION("NAND/SmartMedia driver for AT91RM9200");
+770
drivers/mtd/nand/cafe.c
···
··· 1 + /* 2 + * Driver for One Laptop Per Child ‘CAFÉ’ controller, aka Marvell 88ALP01 3 + * 4 + * Copyright © 2006 Red Hat, Inc. 5 + * Copyright © 2006 David Woodhouse <dwmw2@infradead.org> 6 + */ 7 + 8 + #define DEBUG 9 + 10 + #include <linux/device.h> 11 + #undef DEBUG 12 + #include <linux/mtd/mtd.h> 13 + #include <linux/mtd/nand.h> 14 + #include <linux/pci.h> 15 + #include <linux/delay.h> 16 + #include <linux/interrupt.h> 17 + #include <asm/io.h> 18 + 19 + #define CAFE_NAND_CTRL1 0x00 20 + #define CAFE_NAND_CTRL2 0x04 21 + #define CAFE_NAND_CTRL3 0x08 22 + #define CAFE_NAND_STATUS 0x0c 23 + #define CAFE_NAND_IRQ 0x10 24 + #define CAFE_NAND_IRQ_MASK 0x14 25 + #define CAFE_NAND_DATA_LEN 0x18 26 + #define CAFE_NAND_ADDR1 0x1c 27 + #define CAFE_NAND_ADDR2 0x20 28 + #define CAFE_NAND_TIMING1 0x24 29 + #define CAFE_NAND_TIMING2 0x28 30 + #define CAFE_NAND_TIMING3 0x2c 31 + #define CAFE_NAND_NONMEM 0x30 32 + #define CAFE_NAND_ECC_RESULT 0x3C 33 + #define CAFE_NAND_DMA_CTRL 0x40 34 + #define CAFE_NAND_DMA_ADDR0 0x44 35 + #define CAFE_NAND_DMA_ADDR1 0x48 36 + #define CAFE_NAND_ECC_SYN01 0x50 37 + #define CAFE_NAND_ECC_SYN23 0x54 38 + #define CAFE_NAND_ECC_SYN45 0x58 39 + #define CAFE_NAND_ECC_SYN67 0x5c 40 + #define CAFE_NAND_READ_DATA 0x1000 41 + #define CAFE_NAND_WRITE_DATA 0x2000 42 + 43 + #define CAFE_GLOBAL_CTRL 0x3004 44 + #define CAFE_GLOBAL_IRQ 0x3008 45 + #define CAFE_GLOBAL_IRQ_MASK 0x300c 46 + #define CAFE_NAND_RESET 0x3034 47 + 48 + int cafe_correct_ecc(unsigned char *buf, 49 + unsigned short *chk_syndrome_list); 50 + 51 + struct cafe_priv { 52 + struct nand_chip nand; 53 + struct pci_dev *pdev; 54 + void __iomem *mmio; 55 + uint32_t ctl1; 56 + uint32_t ctl2; 57 + int datalen; 58 + int nr_data; 59 + int data_pos; 60 + int page_addr; 61 + dma_addr_t dmaaddr; 62 + unsigned char *dmabuf; 63 + }; 64 + 65 + static int usedma = 1; 66 + module_param(usedma, int, 0644); 67 + 68 + static int skipbbt = 0; 69 + module_param(skipbbt, int, 0644); 70 + 71 + static int debug = 0; 72 + module_param(debug, int, 0644); 73 + 74 + static int regdebug = 0; 75 + module_param(regdebug, int, 0644); 76 + 77 + static int checkecc = 1; 78 + module_param(checkecc, int, 0644); 79 + 80 + static int slowtiming = 0; 81 + module_param(slowtiming, int, 0644); 82 + 83 + /* Hrm. Why isn't this already conditional on something in the struct device? */ 84 + #define cafe_dev_dbg(dev, args...) do { if (debug) dev_dbg(dev, ##args); } while(0) 85 + 86 + /* Make it easier to switch to PIO if we need to */ 87 + #define cafe_readl(cafe, addr) readl((cafe)->mmio + CAFE_##addr) 88 + #define cafe_writel(cafe, datum, addr) writel(datum, (cafe)->mmio + CAFE_##addr) 89 + 90 + static int cafe_device_ready(struct mtd_info *mtd) 91 + { 92 + struct cafe_priv *cafe = mtd->priv; 93 + int result = !!(cafe_readl(cafe, NAND_STATUS) | 0x40000000); 94 + uint32_t irqs = cafe_readl(cafe, NAND_IRQ); 95 + 96 + cafe_writel(cafe, irqs, NAND_IRQ); 97 + 98 + cafe_dev_dbg(&cafe->pdev->dev, "NAND device is%s ready, IRQ %x (%x) (%x,%x)\n", 99 + result?"":" not", irqs, cafe_readl(cafe, NAND_IRQ), 100 + cafe_readl(cafe, GLOBAL_IRQ), cafe_readl(cafe, GLOBAL_IRQ_MASK)); 101 + 102 + return result; 103 + } 104 + 105 + 106 + static void cafe_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) 107 + { 108 + struct cafe_priv *cafe = mtd->priv; 109 + 110 + if (usedma) 111 + memcpy(cafe->dmabuf + cafe->datalen, buf, len); 112 + else 113 + memcpy_toio(cafe->mmio + CAFE_NAND_WRITE_DATA + cafe->datalen, buf, len); 114 + 115 + cafe->datalen += len; 116 + 117 + cafe_dev_dbg(&cafe->pdev->dev, "Copy 0x%x bytes to write buffer. datalen 0x%x\n", 118 + len, cafe->datalen); 119 + } 120 + 121 + static void cafe_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) 122 + { 123 + struct cafe_priv *cafe = mtd->priv; 124 + 125 + if (usedma) 126 + memcpy(buf, cafe->dmabuf + cafe->datalen, len); 127 + else 128 + memcpy_fromio(buf, cafe->mmio + CAFE_NAND_READ_DATA + cafe->datalen, len); 129 + 130 + cafe_dev_dbg(&cafe->pdev->dev, "Copy 0x%x bytes from position 0x%x in read buffer.\n", 131 + len, cafe->datalen); 132 + cafe->datalen += len; 133 + } 134 + 135 + static uint8_t cafe_read_byte(struct mtd_info *mtd) 136 + { 137 + struct cafe_priv *cafe = mtd->priv; 138 + uint8_t d; 139 + 140 + cafe_read_buf(mtd, &d, 1); 141 + cafe_dev_dbg(&cafe->pdev->dev, "Read %02x\n", d); 142 + 143 + return d; 144 + } 145 + 146 + static void cafe_nand_cmdfunc(struct mtd_info *mtd, unsigned command, 147 + int column, int page_addr) 148 + { 149 + struct cafe_priv *cafe = mtd->priv; 150 + int adrbytes = 0; 151 + uint32_t ctl1; 152 + uint32_t doneint = 0x80000000; 153 + 154 + cafe_dev_dbg(&cafe->pdev->dev, "cmdfunc %02x, 0x%x, 0x%x\n", 155 + command, column, page_addr); 156 + 157 + if (command == NAND_CMD_ERASE2 || command == NAND_CMD_PAGEPROG) { 158 + /* Second half of a command we already calculated */ 159 + cafe_writel(cafe, cafe->ctl2 | 0x100 | command, NAND_CTRL2); 160 + ctl1 = cafe->ctl1; 161 + cafe->ctl2 &= ~(1<<30); 162 + cafe_dev_dbg(&cafe->pdev->dev, "Continue command, ctl1 %08x, #data %d\n", 163 + cafe->ctl1, cafe->nr_data); 164 + goto do_command; 165 + } 166 + /* Reset ECC engine */ 167 + cafe_writel(cafe, 0, NAND_CTRL2); 168 + 169 + /* Emulate NAND_CMD_READOOB on large-page chips */ 170 + if (mtd->writesize > 512 && 171 + command == NAND_CMD_READOOB) { 172 + column += mtd->writesize; 173 + command = NAND_CMD_READ0; 174 + } 175 + 176 + /* FIXME: Do we need to send read command before sending data 177 + for small-page chips, to position the buffer correctly? */ 178 + 179 + if (column != -1) { 180 + cafe_writel(cafe, column, NAND_ADDR1); 181 + adrbytes = 2; 182 + if (page_addr != -1) 183 + goto write_adr2; 184 + } else if (page_addr != -1) { 185 + cafe_writel(cafe, page_addr & 0xffff, NAND_ADDR1); 186 + page_addr >>= 16; 187 + write_adr2: 188 + cafe_writel(cafe, page_addr, NAND_ADDR2); 189 + adrbytes += 2; 190 + if (mtd->size > mtd->writesize << 16) 191 + adrbytes++; 192 + } 193 + 194 + cafe->data_pos = cafe->datalen = 0; 195 + 196 + /* Set command valid bit */ 197 + ctl1 = 0x80000000 | command; 198 + 199 + /* Set RD or WR bits as appropriate */ 200 + if (command == NAND_CMD_READID || command == NAND_CMD_STATUS) { 201 + ctl1 |= (1<<26); /* rd */ 202 + /* Always 5 bytes, for now */ 203 + cafe->datalen = 4; 204 + /* And one address cycle -- even for STATUS, since the controller doesn't work without */ 205 + adrbytes = 1; 206 + } else if (command == NAND_CMD_READ0 || command == NAND_CMD_READ1 || 207 + command == NAND_CMD_READOOB || command == NAND_CMD_RNDOUT) { 208 + ctl1 |= 1<<26; /* rd */ 209 + /* For now, assume just read to end of page */ 210 + cafe->datalen = mtd->writesize + mtd->oobsize - column; 211 + } else if (command == NAND_CMD_SEQIN) 212 + ctl1 |= 1<<25; /* wr */ 213 + 214 + /* Set number of address bytes */ 215 + if (adrbytes) 216 + ctl1 |= ((adrbytes-1)|8) << 27; 217 + 218 + if (command == NAND_CMD_SEQIN || command == NAND_CMD_ERASE1) { 219 + /* Ignore the first command of a pair; the hardware 220 + deals with them both at once, later */ 221 + cafe->ctl1 = ctl1; 222 + cafe_dev_dbg(&cafe->pdev->dev, "Setup for delayed command, ctl1 %08x, dlen %x\n", 223 + cafe->ctl1, cafe->datalen); 224 + return; 225 + } 226 + /* RNDOUT and READ0 commands need a following byte */ 227 + if (command == NAND_CMD_RNDOUT) 228 + cafe_writel(cafe, cafe->ctl2 | 0x100 | NAND_CMD_RNDOUTSTART, NAND_CTRL2); 229 + else if (command == NAND_CMD_READ0 && mtd->writesize > 512) 230 + cafe_writel(cafe, cafe->ctl2 | 0x100 | NAND_CMD_READSTART, NAND_CTRL2); 231 + 232 + do_command: 233 + cafe_dev_dbg(&cafe->pdev->dev, "dlen %x, ctl1 %x, ctl2 %x\n", 234 + cafe->datalen, ctl1, cafe_readl(cafe, NAND_CTRL2)); 235 + 236 + /* NB: The datasheet lies -- we really should be subtracting 1 here */ 237 + cafe_writel(cafe, cafe->datalen, NAND_DATA_LEN); 238 + cafe_writel(cafe, 0x90000000, NAND_IRQ); 239 + if (usedma && (ctl1 & (3<<25))) { 240 + uint32_t dmactl = 0xc0000000 + cafe->datalen; 241 + /* If WR or RD bits set, set up DMA */ 242 + if (ctl1 & (1<<26)) { 243 + /* It's a read */ 244 + dmactl |= (1<<29); 245 + /* ... so it's done when the DMA is done, not just 246 + the command. */ 247 + doneint = 0x10000000; 248 + } 249 + cafe_writel(cafe, dmactl, NAND_DMA_CTRL); 250 + } 251 + cafe->datalen = 0; 252 + 253 + if (unlikely(regdebug)) { 254 + int i; 255 + printk("About to write command %08x to register 0\n", ctl1); 256 + for (i=4; i< 0x5c; i+=4) 257 + printk("Register %x: %08x\n", i, readl(cafe->mmio + i)); 258 + } 259 + 260 + cafe_writel(cafe, ctl1, NAND_CTRL1); 261 + /* Apply this short delay always to ensure that we do wait tWB in 262 + * any case on any machine. */ 263 + ndelay(100); 264 + 265 + if (1) { 266 + int c = 500000; 267 + uint32_t irqs; 268 + 269 + while (c--) { 270 + irqs = cafe_readl(cafe, NAND_IRQ); 271 + if (irqs & doneint) 272 + break; 273 + udelay(1); 274 + if (!(c % 100000)) 275 + cafe_dev_dbg(&cafe->pdev->dev, "Wait for ready, IRQ %x\n", irqs); 276 + cpu_relax(); 277 + } 278 + cafe_writel(cafe, doneint, NAND_IRQ); 279 + cafe_dev_dbg(&cafe->pdev->dev, "Command %x completed after %d usec, irqs %x (%x)\n", 280 + command, 500000-c, irqs, cafe_readl(cafe, NAND_IRQ)); 281 + } 282 + 283 + WARN_ON(cafe->ctl2 & (1<<30)); 284 + 285 + switch (command) { 286 + 287 + case NAND_CMD_CACHEDPROG: 288 + case NAND_CMD_PAGEPROG: 289 + case NAND_CMD_ERASE1: 290 + case NAND_CMD_ERASE2: 291 + case NAND_CMD_SEQIN: 292 + case NAND_CMD_RNDIN: 293 + case NAND_CMD_STATUS: 294 + case NAND_CMD_DEPLETE1: 295 + case NAND_CMD_RNDOUT: 296 + case NAND_CMD_STATUS_ERROR: 297 + case NAND_CMD_STATUS_ERROR0: 298 + case NAND_CMD_STATUS_ERROR1: 299 + case NAND_CMD_STATUS_ERROR2: 300 + case NAND_CMD_STATUS_ERROR3: 301 + cafe_writel(cafe, cafe->ctl2, NAND_CTRL2); 302 + return; 303 + } 304 + nand_wait_ready(mtd); 305 + cafe_writel(cafe, cafe->ctl2, NAND_CTRL2); 306 + } 307 + 308 + static void cafe_select_chip(struct mtd_info *mtd, int chipnr) 309 + { 310 + //struct cafe_priv *cafe = mtd->priv; 311 + // cafe_dev_dbg(&cafe->pdev->dev, "select_chip %d\n", chipnr); 312 + } 313 + 314 + static int cafe_nand_interrupt(int irq, void *id) 315 + { 316 + struct mtd_info *mtd = id; 317 + struct cafe_priv *cafe = mtd->priv; 318 + uint32_t irqs = cafe_readl(cafe, NAND_IRQ); 319 + cafe_writel(cafe, irqs & ~0x90000000, NAND_IRQ); 320 + if (!irqs) 321 + return IRQ_NONE; 322 + 323 + cafe_dev_dbg(&cafe->pdev->dev, "irq, bits %x (%x)\n", irqs, cafe_readl(cafe, NAND_IRQ)); 324 + return IRQ_HANDLED; 325 + } 326 + 327 + static void cafe_nand_bug(struct mtd_info *mtd) 328 + { 329 + BUG(); 330 + } 331 + 332 + static int cafe_nand_write_oob(struct mtd_info *mtd, 333 + struct nand_chip *chip, int page) 334 + { 335 + int status = 0; 336 + 337 + chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page); 338 + chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); 339 + chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); 340 + status = chip->waitfunc(mtd, chip); 341 + 342 + return status & NAND_STATUS_FAIL ? -EIO : 0; 343 + } 344 + 345 + /* Don't use -- use nand_read_oob_std for now */ 346 + static int cafe_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip, 347 + int page, int sndcmd) 348 + { 349 + chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); 350 + chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); 351 + return 1; 352 + } 353 + /** 354 + * cafe_nand_read_page_syndrome - {REPLACABLE] hardware ecc syndrom based page read 355 + * @mtd: mtd info structure 356 + * @chip: nand chip info structure 357 + * @buf: buffer to store read data 358 + * 359 + * The hw generator calculates the error syndrome automatically. Therefor 360 + * we need a special oob layout and handling. 361 + */ 362 + static int cafe_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip, 363 + uint8_t *buf) 364 + { 365 + struct cafe_priv *cafe = mtd->priv; 366 + 367 + cafe_dev_dbg(&cafe->pdev->dev, "ECC result %08x SYN1,2 %08x\n", 368 + cafe_readl(cafe, NAND_ECC_RESULT), 369 + cafe_readl(cafe, NAND_ECC_SYN01)); 370 + 371 + chip->read_buf(mtd, buf, mtd->writesize); 372 + chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); 373 + 374 + if (checkecc && cafe_readl(cafe, NAND_ECC_RESULT) & (1<<18)) { 375 + unsigned short syn[8]; 376 + int i; 377 + 378 + for (i=0; i<8; i+=2) { 379 + uint32_t tmp = cafe_readl(cafe, NAND_ECC_SYN01 + (i*2)); 380 + syn[i] = tmp & 0xfff; 381 + syn[i+1] = (tmp >> 16) & 0xfff; 382 + } 383 + 384 + if ((i = cafe_correct_ecc(buf, syn)) < 0) { 385 + dev_dbg(&cafe->pdev->dev, "Failed to correct ECC at %08x\n", 386 + cafe_readl(cafe, NAND_ADDR2) * 2048); 387 + for (i=0; i< 0x5c; i+=4) 388 + printk("Register %x: %08x\n", i, readl(cafe->mmio + i)); 389 + mtd->ecc_stats.failed++; 390 + } else { 391 + dev_dbg(&cafe->pdev->dev, "Corrected %d symbol errors\n", i); 392 + mtd->ecc_stats.corrected += i; 393 + } 394 + } 395 + 396 + 397 + return 0; 398 + } 399 + 400 + static struct nand_ecclayout cafe_oobinfo_2048 = { 401 + .eccbytes = 14, 402 + .eccpos = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 403 + .oobfree = {{14, 50}} 404 + }; 405 + 406 + /* Ick. The BBT code really ought to be able to work this bit out 407 + for itself from the above, at least for the 2KiB case */ 408 + static uint8_t cafe_bbt_pattern_2048[] = { 'B', 'b', 't', '0' }; 409 + static uint8_t cafe_mirror_pattern_2048[] = { '1', 't', 'b', 'B' }; 410 + 411 + static uint8_t cafe_bbt_pattern_512[] = { 0xBB }; 412 + static uint8_t cafe_mirror_pattern_512[] = { 0xBC }; 413 + 414 + 415 + static struct nand_bbt_descr cafe_bbt_main_descr_2048 = { 416 + .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE 417 + | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP, 418 + .offs = 14, 419 + .len = 4, 420 + .veroffs = 18, 421 + .maxblocks = 4, 422 + .pattern = cafe_bbt_pattern_2048 423 + }; 424 + 425 + static struct nand_bbt_descr cafe_bbt_mirror_descr_2048 = { 426 + .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE 427 + | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP, 428 + .offs = 14, 429 + .len = 4, 430 + .veroffs = 18, 431 + .maxblocks = 4, 432 + .pattern = cafe_mirror_pattern_2048 433 + }; 434 + 435 + static struct nand_ecclayout cafe_oobinfo_512 = { 436 + .eccbytes = 14, 437 + .eccpos = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 438 + .oobfree = {{14, 2}} 439 + }; 440 + 441 + static struct nand_bbt_descr cafe_bbt_main_descr_512 = { 442 + .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE 443 + | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP, 444 + .offs = 14, 445 + .len = 1, 446 + .veroffs = 15, 447 + .maxblocks = 4, 448 + .pattern = cafe_bbt_pattern_512 449 + }; 450 + 451 + static struct nand_bbt_descr cafe_bbt_mirror_descr_512 = { 452 + .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE 453 + | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP, 454 + .offs = 14, 455 + .len = 1, 456 + .veroffs = 15, 457 + .maxblocks = 4, 458 + .pattern = cafe_mirror_pattern_512 459 + }; 460 + 461 + 462 + static void cafe_nand_write_page_lowlevel(struct mtd_info *mtd, 463 + struct nand_chip *chip, const uint8_t *buf) 464 + { 465 + struct cafe_priv *cafe = mtd->priv; 466 + 467 + chip->write_buf(mtd, buf, mtd->writesize); 468 + chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); 469 + 470 + /* Set up ECC autogeneration */ 471 + cafe->ctl2 |= (1<<30); 472 + } 473 + 474 + static int cafe_nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, 475 + const uint8_t *buf, int page, int cached, int raw) 476 + { 477 + int status; 478 + 479 + chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page); 480 + 481 + if (unlikely(raw)) 482 + chip->ecc.write_page_raw(mtd, chip, buf); 483 + else 484 + chip->ecc.write_page(mtd, chip, buf); 485 + 486 + /* 487 + * Cached progamming disabled for now, Not sure if its worth the 488 + * trouble. The speed gain is not very impressive. (2.3->2.6Mib/s) 489 + */ 490 + cached = 0; 491 + 492 + if (!cached || !(chip->options & NAND_CACHEPRG)) { 493 + 494 + chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); 495 + status = chip->waitfunc(mtd, chip); 496 + /* 497 + * See if operation failed and additional status checks are 498 + * available 499 + */ 500 + if ((status & NAND_STATUS_FAIL) && (chip->errstat)) 501 + status = chip->errstat(mtd, chip, FL_WRITING, status, 502 + page); 503 + 504 + if (status & NAND_STATUS_FAIL) 505 + return -EIO; 506 + } else { 507 + chip->cmdfunc(mtd, NAND_CMD_CACHEDPROG, -1, -1); 508 + status = chip->waitfunc(mtd, chip); 509 + } 510 + 511 + #ifdef CONFIG_MTD_NAND_VERIFY_WRITE 512 + /* Send command to read back the data */ 513 + chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page); 514 + 515 + if (chip->verify_buf(mtd, buf, mtd->writesize)) 516 + return -EIO; 517 + #endif 518 + return 0; 519 + } 520 + 521 + static int cafe_nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) 522 + { 523 + return 0; 524 + } 525 + 526 + static int __devinit cafe_nand_probe(struct pci_dev *pdev, 527 + const struct pci_device_id *ent) 528 + { 529 + struct mtd_info *mtd; 530 + struct cafe_priv *cafe; 531 + uint32_t ctrl; 532 + int err = 0; 533 + 534 + err = pci_enable_device(pdev); 535 + if (err) 536 + return err; 537 + 538 + pci_set_master(pdev); 539 + 540 + mtd = kzalloc(sizeof(*mtd) + sizeof(struct cafe_priv), GFP_KERNEL); 541 + if (!mtd) { 542 + dev_warn(&pdev->dev, "failed to alloc mtd_info\n"); 543 + return -ENOMEM; 544 + } 545 + cafe = (void *)(&mtd[1]); 546 + 547 + mtd->priv = cafe; 548 + mtd->owner = THIS_MODULE; 549 + 550 + cafe->pdev = pdev; 551 + cafe->mmio = pci_iomap(pdev, 0, 0); 552 + if (!cafe->mmio) { 553 + dev_warn(&pdev->dev, "failed to iomap\n"); 554 + err = -ENOMEM; 555 + goto out_free_mtd; 556 + } 557 + cafe->dmabuf = dma_alloc_coherent(&cafe->pdev->dev, 2112 + sizeof(struct nand_buffers), 558 + &cafe->dmaaddr, GFP_KERNEL); 559 + if (!cafe->dmabuf) { 560 + err = -ENOMEM; 561 + goto out_ior; 562 + } 563 + cafe->nand.buffers = (void *)cafe->dmabuf + 2112; 564 + 565 + cafe->nand.cmdfunc = cafe_nand_cmdfunc; 566 + cafe->nand.dev_ready = cafe_device_ready; 567 + cafe->nand.read_byte = cafe_read_byte; 568 + cafe->nand.read_buf = cafe_read_buf; 569 + cafe->nand.write_buf = cafe_write_buf; 570 + cafe->nand.select_chip = cafe_select_chip; 571 + 572 + cafe->nand.chip_delay = 0; 573 + 574 + /* Enable the following for a flash based bad block table */ 575 + cafe->nand.options = NAND_USE_FLASH_BBT | NAND_NO_AUTOINCR | NAND_OWN_BUFFERS; 576 + 577 + if (skipbbt) { 578 + cafe->nand.options |= NAND_SKIP_BBTSCAN; 579 + cafe->nand.block_bad = cafe_nand_block_bad; 580 + } 581 + 582 + /* Start off by resetting the NAND controller completely */ 583 + cafe_writel(cafe, 1, NAND_RESET); 584 + cafe_writel(cafe, 0, NAND_RESET); 585 + 586 + cafe_writel(cafe, 0xffffffff, NAND_IRQ_MASK); 587 + 588 + /* Timings from Marvell's test code (not verified or calculated by us) */ 589 + if (!slowtiming) { 590 + cafe_writel(cafe, 0x01010a0a, NAND_TIMING1); 591 + cafe_writel(cafe, 0x24121212, NAND_TIMING2); 592 + cafe_writel(cafe, 0x11000000, NAND_TIMING3); 593 + } else { 594 + cafe_writel(cafe, 0xffffffff, NAND_TIMING1); 595 + cafe_writel(cafe, 0xffffffff, NAND_TIMING2); 596 + cafe_writel(cafe, 0xffffffff, NAND_TIMING3); 597 + } 598 + cafe_writel(cafe, 0xffffffff, NAND_IRQ_MASK); 599 + err = request_irq(pdev->irq, &cafe_nand_interrupt, SA_SHIRQ, "CAFE NAND", mtd); 600 + if (err) { 601 + dev_warn(&pdev->dev, "Could not register IRQ %d\n", pdev->irq); 602 + 603 + goto out_free_dma; 604 + } 605 + #if 1 606 + /* Disable master reset, enable NAND clock */ 607 + ctrl = cafe_readl(cafe, GLOBAL_CTRL); 608 + ctrl &= 0xffffeff0; 609 + ctrl |= 0x00007000; 610 + cafe_writel(cafe, ctrl | 0x05, GLOBAL_CTRL); 611 + cafe_writel(cafe, ctrl | 0x0a, GLOBAL_CTRL); 612 + cafe_writel(cafe, 0, NAND_DMA_CTRL); 613 + 614 + cafe_writel(cafe, 0x7006, GLOBAL_CTRL); 615 + cafe_writel(cafe, 0x700a, GLOBAL_CTRL); 616 + 617 + /* Set up DMA address */ 618 + cafe_writel(cafe, cafe->dmaaddr & 0xffffffff, NAND_DMA_ADDR0); 619 + if (sizeof(cafe->dmaaddr) > 4) 620 + /* Shift in two parts to shut the compiler up */ 621 + cafe_writel(cafe, (cafe->dmaaddr >> 16) >> 16, NAND_DMA_ADDR1); 622 + else 623 + cafe_writel(cafe, 0, NAND_DMA_ADDR1); 624 + 625 + cafe_dev_dbg(&cafe->pdev->dev, "Set DMA address to %x (virt %p)\n", 626 + cafe_readl(cafe, NAND_DMA_ADDR0), cafe->dmabuf); 627 + 628 + /* Enable NAND IRQ in global IRQ mask register */ 629 + cafe_writel(cafe, 0x80000007, GLOBAL_IRQ_MASK); 630 + cafe_dev_dbg(&cafe->pdev->dev, "Control %x, IRQ mask %x\n", 631 + cafe_readl(cafe, GLOBAL_CTRL), cafe_readl(cafe, GLOBAL_IRQ_MASK)); 632 + #endif 633 + #if 1 634 + mtd->writesize=2048; 635 + mtd->oobsize = 0x40; 636 + memset(cafe->dmabuf, 0x5a, 2112); 637 + cafe->nand.cmdfunc(mtd, NAND_CMD_READID, 0, -1); 638 + cafe->nand.read_byte(mtd); 639 + cafe->nand.read_byte(mtd); 640 + cafe->nand.read_byte(mtd); 641 + cafe->nand.read_byte(mtd); 642 + cafe->nand.read_byte(mtd); 643 + #endif 644 + #if 0 645 + cafe->nand.cmdfunc(mtd, NAND_CMD_READ0, 0, 0); 646 + // nand_wait_ready(mtd); 647 + cafe->nand.read_byte(mtd); 648 + cafe->nand.read_byte(mtd); 649 + cafe->nand.read_byte(mtd); 650 + cafe->nand.read_byte(mtd); 651 + #endif 652 + #if 0 653 + writel(0x84600070, cafe->mmio); 654 + udelay(10); 655 + cafe_dev_dbg(&cafe->pdev->dev, "Status %x\n", cafe_readl(cafe, NAND_NONMEM)); 656 + #endif 657 + /* Scan to find existance of the device */ 658 + if (nand_scan_ident(mtd, 1)) { 659 + err = -ENXIO; 660 + goto out_irq; 661 + } 662 + 663 + cafe->ctl2 = 1<<27; /* Reed-Solomon ECC */ 664 + if (mtd->writesize == 2048) 665 + cafe->ctl2 |= 1<<29; /* 2KiB page size */ 666 + 667 + /* Set up ECC according to the type of chip we found */ 668 + if (mtd->writesize == 2048) { 669 + cafe->nand.ecc.layout = &cafe_oobinfo_2048; 670 + cafe->nand.bbt_td = &cafe_bbt_main_descr_2048; 671 + cafe->nand.bbt_md = &cafe_bbt_mirror_descr_2048; 672 + } else if (mtd->writesize == 512) { 673 + cafe->nand.ecc.layout = &cafe_oobinfo_512; 674 + cafe->nand.bbt_td = &cafe_bbt_main_descr_512; 675 + cafe->nand.bbt_md = &cafe_bbt_mirror_descr_512; 676 + } else { 677 + printk(KERN_WARNING "Unexpected NAND flash writesize %d. Aborting\n", 678 + mtd->writesize); 679 + goto out_irq; 680 + } 681 + cafe->nand.ecc.mode = NAND_ECC_HW_SYNDROME; 682 + cafe->nand.ecc.size = mtd->writesize; 683 + cafe->nand.ecc.bytes = 14; 684 + cafe->nand.ecc.hwctl = (void *)cafe_nand_bug; 685 + cafe->nand.ecc.calculate = (void *)cafe_nand_bug; 686 + cafe->nand.ecc.correct = (void *)cafe_nand_bug; 687 + cafe->nand.write_page = cafe_nand_write_page; 688 + cafe->nand.ecc.write_page = cafe_nand_write_page_lowlevel; 689 + cafe->nand.ecc.write_oob = cafe_nand_write_oob; 690 + cafe->nand.ecc.read_page = cafe_nand_read_page; 691 + cafe->nand.ecc.read_oob = cafe_nand_read_oob; 692 + 693 + err = nand_scan_tail(mtd); 694 + if (err) 695 + goto out_irq; 696 + 697 + pci_set_drvdata(pdev, mtd); 698 + add_mtd_device(mtd); 699 + goto out; 700 + 701 + out_irq: 702 + /* Disable NAND IRQ in global IRQ mask register */ 703 + cafe_writel(cafe, ~1 & cafe_readl(cafe, GLOBAL_IRQ_MASK), GLOBAL_IRQ_MASK); 704 + free_irq(pdev->irq, mtd); 705 + out_free_dma: 706 + dma_free_coherent(&cafe->pdev->dev, 2112, cafe->dmabuf, cafe->dmaaddr); 707 + out_ior: 708 + pci_iounmap(pdev, cafe->mmio); 709 + out_free_mtd: 710 + kfree(mtd); 711 + out: 712 + return err; 713 + } 714 + 715 + static void __devexit cafe_nand_remove(struct pci_dev *pdev) 716 + { 717 + struct mtd_info *mtd = pci_get_drvdata(pdev); 718 + struct cafe_priv *cafe = mtd->priv; 719 + 720 + del_mtd_device(mtd); 721 + /* Disable NAND IRQ in global IRQ mask register */ 722 + cafe_writel(cafe, ~1 & cafe_readl(cafe, GLOBAL_IRQ_MASK), GLOBAL_IRQ_MASK); 723 + free_irq(pdev->irq, mtd); 724 + nand_release(mtd); 725 + pci_iounmap(pdev, cafe->mmio); 726 + dma_free_coherent(&cafe->pdev->dev, 2112, cafe->dmabuf, cafe->dmaaddr); 727 + kfree(mtd); 728 + } 729 + 730 + static struct pci_device_id cafe_nand_tbl[] = { 731 + { 0x11ab, 0x4100, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MEMORY_FLASH << 8, 0xFFFF0 } 732 + }; 733 + 734 + MODULE_DEVICE_TABLE(pci, cafe_nand_tbl); 735 + 736 + static struct pci_driver cafe_nand_pci_driver = { 737 + .name = "CAFÉ NAND", 738 + .id_table = cafe_nand_tbl, 739 + .probe = cafe_nand_probe, 740 + .remove = __devexit_p(cafe_nand_remove), 741 + #ifdef CONFIG_PMx 742 + .suspend = cafe_nand_suspend, 743 + .resume = cafe_nand_resume, 744 + #endif 745 + }; 746 + 747 + static int cafe_nand_init(void) 748 + { 749 + return pci_register_driver(&cafe_nand_pci_driver); 750 + } 751 + 752 + static void cafe_nand_exit(void) 753 + { 754 + pci_unregister_driver(&cafe_nand_pci_driver); 755 + } 756 + module_init(cafe_nand_init); 757 + module_exit(cafe_nand_exit); 758 + 759 + MODULE_LICENSE("GPL"); 760 + MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>"); 761 + MODULE_DESCRIPTION("NAND flash driver for OLPC CAFE chip"); 762 + 763 + /* Correct ECC for 2048 bytes of 0xff: 764 + 41 a0 71 65 54 27 f3 93 ec a9 be ed 0b a1 */ 765 + 766 + /* dwmw2's B-test board, in case of completely screwing it: 767 + Bad eraseblock 2394 at 0x12b40000 768 + Bad eraseblock 2627 at 0x14860000 769 + Bad eraseblock 3349 at 0x1a2a0000 770 + */
+1381
drivers/mtd/nand/cafe_ecc.c
···
··· 1 + /* Error correction for CAFÉ NAND controller 2 + * 3 + * © 2006 Marvell, Inc. 4 + * Author: Tom Chiou 5 + * 6 + * This program is free software; you can redistribute it and/or modify it 7 + * under the terms of the GNU General Public License as published by the Free 8 + * Software Foundation; either version 2 of the License, or (at your option) 9 + * any later version. 10 + * 11 + * This program is distributed in the hope that it will be useful, but WITHOUT 12 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 14 + * more details. 15 + * 16 + * You should have received a copy of the GNU General Public License along with 17 + * this program; if not, write to the Free Software Foundation, Inc., 59 18 + * Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 + */ 20 + 21 + #include <linux/kernel.h> 22 + #include <linux/module.h> 23 + #include <linux/errno.h> 24 + 25 + static unsigned short gf4096_mul(unsigned short, unsigned short); 26 + static unsigned short gf64_mul(unsigned short, unsigned short); 27 + static unsigned short gf4096_inv(unsigned short); 28 + static unsigned short err_pos(unsigned short); 29 + static void find_4bit_err_coefs(unsigned short, unsigned short, unsigned short, 30 + unsigned short, unsigned short, unsigned short, 31 + unsigned short, unsigned short, unsigned short *); 32 + static void zero_4x5_col3(unsigned short[4][5]); 33 + static void zero_4x5_col2(unsigned short[4][5]); 34 + static void zero_4x5_col1(unsigned short[4][5]); 35 + static void swap_4x5_rows(unsigned short[4][5], int, int, int); 36 + static void swap_2x3_rows(unsigned short m[2][3]); 37 + static void solve_4x5(unsigned short m[4][5], unsigned short *, int *); 38 + static void sort_coefs(int *, unsigned short *, int); 39 + static void find_4bit_err_pats(unsigned short, unsigned short, unsigned short, 40 + unsigned short, unsigned short, unsigned short, 41 + unsigned short, unsigned short, unsigned short *); 42 + static void find_3bit_err_coefs(unsigned short, unsigned short, unsigned short, 43 + unsigned short, unsigned short, unsigned short, 44 + unsigned short *); 45 + static void zero_3x4_col2(unsigned short[3][4]); 46 + static void zero_3x4_col1(unsigned short[3][4]); 47 + static void swap_3x4_rows(unsigned short[3][4], int, int, int); 48 + static void solve_3x4(unsigned short[3][4], unsigned short *, int *); 49 + static void find_3bit_err_pats(unsigned short, unsigned short, unsigned short, 50 + unsigned short, unsigned short, unsigned short, 51 + unsigned short *); 52 + 53 + static void find_2bit_err_pats(unsigned short, unsigned short, unsigned short, 54 + unsigned short, unsigned short *); 55 + static void find_2x2_soln(unsigned short, unsigned short, unsigned short, 56 + unsigned short, unsigned short, unsigned short, 57 + unsigned short *); 58 + static void solve_2x3(unsigned short[2][3], unsigned short *); 59 + static int chk_no_err_only(unsigned short *, unsigned short *); 60 + static int chk_1_err_only(unsigned short *, unsigned short *); 61 + static int chk_2_err_only(unsigned short *, unsigned short *); 62 + static int chk_3_err_only(unsigned short *, unsigned short *); 63 + static int chk_4_err_only(unsigned short *, unsigned short *); 64 + 65 + static unsigned short gf64_mul(unsigned short a, unsigned short b) 66 + { 67 + unsigned short tmp1, tmp2, tmp3, tmp4, tmp5; 68 + unsigned short c_bit0, c_bit1, c_bit2, c_bit3, c_bit4, c_bit5, c; 69 + 70 + tmp1 = ((a) ^ (a >> 5)); 71 + tmp2 = ((a >> 4) ^ (a >> 5)); 72 + tmp3 = ((a >> 3) ^ (a >> 4)); 73 + tmp4 = ((a >> 2) ^ (a >> 3)); 74 + tmp5 = ((a >> 1) ^ (a >> 2)); 75 + 76 + c_bit0 = ((a & b) ^ ((a >> 5) & (b >> 1)) ^ ((a >> 4) & (b >> 2)) ^ 77 + ((a >> 3) & (b >> 3)) ^ ((a >> 2) & (b >> 4)) ^ ((a >> 1) & (b >> 5))) & 0x1; 78 + 79 + c_bit1 = (((a >> 1) & b) ^ (tmp1 & (b >> 1)) ^ (tmp2 & (b >> 2)) ^ 80 + (tmp3 & (b >> 3)) ^ (tmp4 & (b >> 4)) ^ (tmp5 & (b >> 5))) & 0x1; 81 + 82 + c_bit2 = (((a >> 2) & b) ^ ((a >> 1) & (b >> 1)) ^ (tmp1 & (b >> 2)) ^ 83 + (tmp2 & (b >> 3)) ^ (tmp3 & (b >> 4)) ^ (tmp4 & (b >> 5))) & 0x1; 84 + 85 + c_bit3 = (((a >> 3) & b) ^ ((a >> 2) & (b >> 1)) ^ ((a >> 1) & (b >> 2)) ^ 86 + (tmp1 & (b >> 3)) ^ (tmp2 & (b >> 4)) ^ (tmp3 & (b >> 5))) & 0x1; 87 + 88 + c_bit4 = (((a >> 4) & b) ^ ((a >> 3) & (b >> 1)) ^ ((a >> 2) & (b >> 2)) ^ 89 + ((a >> 1) & (b >> 3)) ^ (tmp1 & (b >> 4)) ^ (tmp2 & (b >> 5))) & 0x1; 90 + 91 + c_bit5 = (((a >> 5) & b) ^ ((a >> 4) & (b >> 1)) ^ ((a >> 3) & (b >> 2)) ^ 92 + ((a >> 2) & (b >> 3)) ^ ((a >> 1) & (b >> 4)) ^ (tmp1 & (b >> 5))) & 0x1; 93 + 94 + c = c_bit0 | (c_bit1 << 1) | (c_bit2 << 2) | (c_bit3 << 3) | (c_bit4 << 4) | (c_bit5 << 5); 95 + 96 + return c; 97 + } 98 + 99 + static unsigned short gf4096_mul(unsigned short a, unsigned short b) 100 + { 101 + unsigned short ah, al, bh, bl, alxah, blxbh, ablh, albl, ahbh, ahbhB, c; 102 + 103 + ah = (a >> 6) & 0x3f; 104 + al = a & 0x3f; 105 + bh = (b >> 6) & 0x3f; 106 + bl = b & 0x3f; 107 + alxah = al ^ ah; 108 + blxbh = bl ^ bh; 109 + 110 + ablh = gf64_mul(alxah, blxbh); 111 + albl = gf64_mul(al, bl); 112 + ahbh = gf64_mul(ah, bh); 113 + 114 + ahbhB = ((ahbh & 0x1) << 5) | 115 + ((ahbh & 0x20) >> 1) | 116 + ((ahbh & 0x10) >> 1) | ((ahbh & 0x8) >> 1) | ((ahbh & 0x4) >> 1) | (((ahbh >> 1) ^ ahbh) & 0x1); 117 + 118 + c = ((ablh ^ albl) << 6) | (ahbhB ^ albl); 119 + return c; 120 + } 121 + 122 + static void find_2bit_err_pats(unsigned short s0, unsigned short s1, unsigned short r0, unsigned short r1, unsigned short *pats) 123 + { 124 + find_2x2_soln(0x1, 0x1, r0, r1, s0, s1, pats); 125 + } 126 + 127 + static void find_3bit_err_coefs(unsigned short s0, unsigned short s1, 128 + unsigned short s2, unsigned short s3, unsigned short s4, unsigned short s5, unsigned short *coefs) 129 + { 130 + unsigned short m[3][4]; 131 + int row_order[3]; 132 + 133 + row_order[0] = 0; 134 + row_order[1] = 1; 135 + row_order[2] = 2; 136 + m[0][0] = s2; 137 + m[0][1] = s1; 138 + m[0][2] = s0; 139 + m[0][3] = s3; 140 + m[1][0] = s3; 141 + m[1][1] = s2; 142 + m[1][2] = s1; 143 + m[1][3] = s4; 144 + m[2][0] = s4; 145 + m[2][1] = s3; 146 + m[2][2] = s2; 147 + m[2][3] = s5; 148 + 149 + if (m[0][2] != 0x0) { 150 + zero_3x4_col2(m); 151 + } else if (m[1][2] != 0x0) { 152 + swap_3x4_rows(m, 0, 1, 4); 153 + zero_3x4_col2(m); 154 + } else if (m[2][2] != 0x0) { 155 + swap_3x4_rows(m, 0, 2, 4); 156 + zero_3x4_col2(m); 157 + } else { 158 + printk(KERN_ERR "Error: find_3bit_err_coefs, s0,s1,s2 all zeros!\n"); 159 + } 160 + 161 + if (m[1][1] != 0x0) { 162 + zero_3x4_col1(m); 163 + } else if (m[2][1] != 0x0) { 164 + swap_3x4_rows(m, 1, 2, 4); 165 + zero_3x4_col1(m); 166 + } else { 167 + printk(KERN_ERR "Error: find_3bit_err_coefs, cannot resolve col 1!\n"); 168 + } 169 + 170 + /* solve coefs */ 171 + solve_3x4(m, coefs, row_order); 172 + } 173 + 174 + static void zero_3x4_col2(unsigned short m[3][4]) 175 + { 176 + unsigned short minv1, minv2; 177 + 178 + minv1 = gf4096_mul(m[1][2], gf4096_inv(m[0][2])); 179 + minv2 = gf4096_mul(m[2][2], gf4096_inv(m[0][2])); 180 + m[1][0] = m[1][0] ^ gf4096_mul(m[0][0], minv1); 181 + m[1][1] = m[1][1] ^ gf4096_mul(m[0][1], minv1); 182 + m[1][3] = m[1][3] ^ gf4096_mul(m[0][3], minv1); 183 + m[2][0] = m[2][0] ^ gf4096_mul(m[0][0], minv2); 184 + m[2][1] = m[2][1] ^ gf4096_mul(m[0][1], minv2); 185 + m[2][3] = m[2][3] ^ gf4096_mul(m[0][3], minv2); 186 + } 187 + 188 + static void zero_3x4_col1(unsigned short m[3][4]) 189 + { 190 + unsigned short minv; 191 + minv = gf4096_mul(m[2][1], gf4096_inv(m[1][1])); 192 + m[2][0] = m[2][0] ^ gf4096_mul(m[1][0], minv); 193 + m[2][3] = m[2][3] ^ gf4096_mul(m[1][3], minv); 194 + } 195 + 196 + static void swap_3x4_rows(unsigned short m[3][4], int i, int j, int col_width) 197 + { 198 + unsigned short tmp0; 199 + int cnt; 200 + for (cnt = 0; cnt < col_width; cnt++) { 201 + tmp0 = m[i][cnt]; 202 + m[i][cnt] = m[j][cnt]; 203 + m[j][cnt] = tmp0; 204 + } 205 + } 206 + 207 + static void solve_3x4(unsigned short m[3][4], unsigned short *coefs, int *row_order) 208 + { 209 + unsigned short tmp[3]; 210 + tmp[0] = gf4096_mul(m[2][3], gf4096_inv(m[2][0])); 211 + tmp[1] = gf4096_mul((gf4096_mul(tmp[0], m[1][0]) ^ m[1][3]), gf4096_inv(m[1][1])); 212 + tmp[2] = gf4096_mul((gf4096_mul(tmp[0], m[0][0]) ^ gf4096_mul(tmp[1], m[0][1]) ^ m[0][3]), gf4096_inv(m[0][2])); 213 + sort_coefs(row_order, tmp, 3); 214 + coefs[0] = tmp[0]; 215 + coefs[1] = tmp[1]; 216 + coefs[2] = tmp[2]; 217 + } 218 + 219 + static void find_3bit_err_pats(unsigned short s0, unsigned short s1, 220 + unsigned short s2, unsigned short r0, 221 + unsigned short r1, unsigned short r2, 222 + unsigned short *pats) 223 + { 224 + find_2x2_soln(r0 ^ r2, r1 ^ r2, 225 + gf4096_mul(r0, r0 ^ r2), gf4096_mul(r1, r1 ^ r2), 226 + gf4096_mul(s0, r2) ^ s1, gf4096_mul(s1, r2) ^ s2, pats); 227 + pats[2] = s0 ^ pats[0] ^ pats[1]; 228 + } 229 + 230 + static void find_4bit_err_coefs(unsigned short s0, unsigned short s1, 231 + unsigned short s2, unsigned short s3, 232 + unsigned short s4, unsigned short s5, 233 + unsigned short s6, unsigned short s7, 234 + unsigned short *coefs) 235 + { 236 + unsigned short m[4][5]; 237 + int row_order[4]; 238 + 239 + row_order[0] = 0; 240 + row_order[1] = 1; 241 + row_order[2] = 2; 242 + row_order[3] = 3; 243 + 244 + m[0][0] = s3; 245 + m[0][1] = s2; 246 + m[0][2] = s1; 247 + m[0][3] = s0; 248 + m[0][4] = s4; 249 + m[1][0] = s4; 250 + m[1][1] = s3; 251 + m[1][2] = s2; 252 + m[1][3] = s1; 253 + m[1][4] = s5; 254 + m[2][0] = s5; 255 + m[2][1] = s4; 256 + m[2][2] = s3; 257 + m[2][3] = s2; 258 + m[2][4] = s6; 259 + m[3][0] = s6; 260 + m[3][1] = s5; 261 + m[3][2] = s4; 262 + m[3][3] = s3; 263 + m[3][4] = s7; 264 + 265 + if (m[0][3] != 0x0) { 266 + zero_4x5_col3(m); 267 + } else if (m[1][3] != 0x0) { 268 + swap_4x5_rows(m, 0, 1, 5); 269 + zero_4x5_col3(m); 270 + } else if (m[2][3] != 0x0) { 271 + swap_4x5_rows(m, 0, 2, 5); 272 + zero_4x5_col3(m); 273 + } else if (m[3][3] != 0x0) { 274 + swap_4x5_rows(m, 0, 3, 5); 275 + zero_4x5_col3(m); 276 + } else { 277 + printk(KERN_ERR "Error: find_4bit_err_coefs, s0,s1,s2,s3 all zeros!\n"); 278 + } 279 + 280 + if (m[1][2] != 0x0) { 281 + zero_4x5_col2(m); 282 + } else if (m[2][2] != 0x0) { 283 + swap_4x5_rows(m, 1, 2, 5); 284 + zero_4x5_col2(m); 285 + } else if (m[3][2] != 0x0) { 286 + swap_4x5_rows(m, 1, 3, 5); 287 + zero_4x5_col2(m); 288 + } else { 289 + printk(KERN_ERR "Error: find_4bit_err_coefs, cannot resolve col 2!\n"); 290 + } 291 + 292 + if (m[2][1] != 0x0) { 293 + zero_4x5_col1(m); 294 + } else if (m[3][1] != 0x0) { 295 + swap_4x5_rows(m, 2, 3, 5); 296 + zero_4x5_col1(m); 297 + } else { 298 + printk(KERN_ERR "Error: find_4bit_err_coefs, cannot resolve col 1!\n"); 299 + } 300 + 301 + solve_4x5(m, coefs, row_order); 302 + } 303 + 304 + static void zero_4x5_col3(unsigned short m[4][5]) 305 + { 306 + unsigned short minv1, minv2, minv3; 307 + 308 + minv1 = gf4096_mul(m[1][3], gf4096_inv(m[0][3])); 309 + minv2 = gf4096_mul(m[2][3], gf4096_inv(m[0][3])); 310 + minv3 = gf4096_mul(m[3][3], gf4096_inv(m[0][3])); 311 + 312 + m[1][0] = m[1][0] ^ gf4096_mul(m[0][0], minv1); 313 + m[1][1] = m[1][1] ^ gf4096_mul(m[0][1], minv1); 314 + m[1][2] = m[1][2] ^ gf4096_mul(m[0][2], minv1); 315 + m[1][4] = m[1][4] ^ gf4096_mul(m[0][4], minv1); 316 + m[2][0] = m[2][0] ^ gf4096_mul(m[0][0], minv2); 317 + m[2][1] = m[2][1] ^ gf4096_mul(m[0][1], minv2); 318 + m[2][2] = m[2][2] ^ gf4096_mul(m[0][2], minv2); 319 + m[2][4] = m[2][4] ^ gf4096_mul(m[0][4], minv2); 320 + m[3][0] = m[3][0] ^ gf4096_mul(m[0][0], minv3); 321 + m[3][1] = m[3][1] ^ gf4096_mul(m[0][1], minv3); 322 + m[3][2] = m[3][2] ^ gf4096_mul(m[0][2], minv3); 323 + m[3][4] = m[3][4] ^ gf4096_mul(m[0][4], minv3); 324 + } 325 + 326 + static void zero_4x5_col2(unsigned short m[4][5]) 327 + { 328 + unsigned short minv2, minv3; 329 + 330 + minv2 = gf4096_mul(m[2][2], gf4096_inv(m[1][2])); 331 + minv3 = gf4096_mul(m[3][2], gf4096_inv(m[1][2])); 332 + 333 + m[2][0] = m[2][0] ^ gf4096_mul(m[1][0], minv2); 334 + m[2][1] = m[2][1] ^ gf4096_mul(m[1][1], minv2); 335 + m[2][4] = m[2][4] ^ gf4096_mul(m[1][4], minv2); 336 + m[3][0] = m[3][0] ^ gf4096_mul(m[1][0], minv3); 337 + m[3][1] = m[3][1] ^ gf4096_mul(m[1][1], minv3); 338 + m[3][4] = m[3][4] ^ gf4096_mul(m[1][4], minv3); 339 + } 340 + 341 + static void zero_4x5_col1(unsigned short m[4][5]) 342 + { 343 + unsigned short minv; 344 + 345 + minv = gf4096_mul(m[3][1], gf4096_inv(m[2][1])); 346 + 347 + m[3][0] = m[3][0] ^ gf4096_mul(m[2][0], minv); 348 + m[3][4] = m[3][4] ^ gf4096_mul(m[2][4], minv); 349 + } 350 + 351 + static void swap_4x5_rows(unsigned short m[4][5], int i, int j, int col_width) 352 + { 353 + unsigned short tmp0; 354 + int cnt; 355 + 356 + for (cnt = 0; cnt < col_width; cnt++) { 357 + tmp0 = m[i][cnt]; 358 + m[i][cnt] = m[j][cnt]; 359 + m[j][cnt] = tmp0; 360 + } 361 + } 362 + 363 + static void solve_4x5(unsigned short m[4][5], unsigned short *coefs, int *row_order) 364 + { 365 + unsigned short tmp[4]; 366 + 367 + tmp[0] = gf4096_mul(m[3][4], gf4096_inv(m[3][0])); 368 + tmp[1] = gf4096_mul((gf4096_mul(tmp[0], m[2][0]) ^ m[2][4]), gf4096_inv(m[2][1])); 369 + tmp[2] = gf4096_mul((gf4096_mul(tmp[0], m[1][0]) ^ gf4096_mul(tmp[1], m[1][1]) ^ m[1][4]), gf4096_inv(m[1][2])); 370 + tmp[3] = gf4096_mul((gf4096_mul(tmp[0], m[0][0]) ^ 371 + gf4096_mul(tmp[1], m[0][1]) ^ gf4096_mul(tmp[2], m[0][2]) ^ m[0][4]), gf4096_inv(m[0][3])); 372 + sort_coefs(row_order, tmp, 4); 373 + coefs[0] = tmp[0]; 374 + coefs[1] = tmp[1]; 375 + coefs[2] = tmp[2]; 376 + coefs[3] = tmp[3]; 377 + } 378 + 379 + static void sort_coefs(int *order, unsigned short *soln, int len) 380 + { 381 + int cnt, start_cnt, least_ord, least_cnt; 382 + unsigned short tmp0; 383 + for (start_cnt = 0; start_cnt < len; start_cnt++) { 384 + for (cnt = start_cnt; cnt < len; cnt++) { 385 + if (cnt == start_cnt) { 386 + least_ord = order[cnt]; 387 + least_cnt = start_cnt; 388 + } else { 389 + if (least_ord > order[cnt]) { 390 + least_ord = order[cnt]; 391 + least_cnt = cnt; 392 + } 393 + } 394 + } 395 + if (least_cnt != start_cnt) { 396 + tmp0 = order[least_cnt]; 397 + order[least_cnt] = order[start_cnt]; 398 + order[start_cnt] = tmp0; 399 + tmp0 = soln[least_cnt]; 400 + soln[least_cnt] = soln[start_cnt]; 401 + soln[start_cnt] = tmp0; 402 + } 403 + } 404 + } 405 + 406 + static void find_4bit_err_pats(unsigned short s0, unsigned short s1, 407 + unsigned short s2, unsigned short s3, 408 + unsigned short z1, unsigned short z2, 409 + unsigned short z3, unsigned short z4, 410 + unsigned short *pats) 411 + { 412 + unsigned short z4_z1, z3z4_z3z3, z4_z2, s0z4_s1, z1z4_z1z1, 413 + z4_z3, z2z4_z2z2, s1z4_s2, z3z3z4_z3z3z3, z1z1z4_z1z1z1, z2z2z4_z2z2z2, s2z4_s3; 414 + unsigned short tmp0, tmp1, tmp2, tmp3; 415 + 416 + z4_z1 = z4 ^ z1; 417 + z3z4_z3z3 = gf4096_mul(z3, z4) ^ gf4096_mul(z3, z3); 418 + z4_z2 = z4 ^ z2; 419 + s0z4_s1 = gf4096_mul(s0, z4) ^ s1; 420 + z1z4_z1z1 = gf4096_mul(z1, z4) ^ gf4096_mul(z1, z1); 421 + z4_z3 = z4 ^ z3; 422 + z2z4_z2z2 = gf4096_mul(z2, z4) ^ gf4096_mul(z2, z2); 423 + s1z4_s2 = gf4096_mul(s1, z4) ^ s2; 424 + z3z3z4_z3z3z3 = gf4096_mul(gf4096_mul(z3, z3), z4) ^ gf4096_mul(gf4096_mul(z3, z3), z3); 425 + z1z1z4_z1z1z1 = gf4096_mul(gf4096_mul(z1, z1), z4) ^ gf4096_mul(gf4096_mul(z1, z1), z1); 426 + z2z2z4_z2z2z2 = gf4096_mul(gf4096_mul(z2, z2), z4) ^ gf4096_mul(gf4096_mul(z2, z2), z2); 427 + s2z4_s3 = gf4096_mul(s2, z4) ^ s3; 428 + 429 + //find err pat 0,1 430 + find_2x2_soln(gf4096_mul(z4_z1, z3z4_z3z3) ^ 431 + gf4096_mul(z1z4_z1z1, z4_z3), gf4096_mul(z4_z2, 432 + z3z4_z3z3) ^ 433 + gf4096_mul(z2z4_z2z2, z4_z3), gf4096_mul(z1z4_z1z1, 434 + z3z3z4_z3z3z3) ^ 435 + gf4096_mul(z1z1z4_z1z1z1, z3z4_z3z3), 436 + gf4096_mul(z2z4_z2z2, 437 + z3z3z4_z3z3z3) ^ gf4096_mul(z2z2z4_z2z2z2, 438 + z3z4_z3z3), 439 + gf4096_mul(s0z4_s1, z3z4_z3z3) ^ gf4096_mul(s1z4_s2, 440 + z4_z3), 441 + gf4096_mul(s1z4_s2, z3z3z4_z3z3z3) ^ gf4096_mul(s2z4_s3, z3z4_z3z3), pats); 442 + tmp0 = pats[0]; 443 + tmp1 = pats[1]; 444 + tmp2 = pats[0] ^ pats[1] ^ s0; 445 + tmp3 = gf4096_mul(pats[0], z1) ^ gf4096_mul(pats[1], z2) ^ s1; 446 + 447 + //find err pat 2,3 448 + find_2x2_soln(0x1, 0x1, z3, z4, tmp2, tmp3, pats); 449 + pats[2] = pats[0]; 450 + pats[3] = pats[1]; 451 + pats[0] = tmp0; 452 + pats[1] = tmp1; 453 + } 454 + 455 + static void find_2x2_soln(unsigned short c00, unsigned short c01, 456 + unsigned short c10, unsigned short c11, 457 + unsigned short lval0, unsigned short lval1, 458 + unsigned short *soln) 459 + { 460 + unsigned short m[2][3]; 461 + m[0][0] = c00; 462 + m[0][1] = c01; 463 + m[0][2] = lval0; 464 + m[1][0] = c10; 465 + m[1][1] = c11; 466 + m[1][2] = lval1; 467 + 468 + if (m[0][1] != 0x0) { 469 + /* */ 470 + } else if (m[1][1] != 0x0) { 471 + swap_2x3_rows(m); 472 + } else { 473 + printk(KERN_ERR "Warning: find_2bit_err_coefs, s0,s1 all zeros!\n"); 474 + } 475 + 476 + solve_2x3(m, soln); 477 + } 478 + 479 + static void swap_2x3_rows(unsigned short m[2][3]) 480 + { 481 + unsigned short tmp0; 482 + int cnt; 483 + 484 + for (cnt = 0; cnt < 3; cnt++) { 485 + tmp0 = m[0][cnt]; 486 + m[0][cnt] = m[1][cnt]; 487 + m[1][cnt] = tmp0; 488 + } 489 + } 490 + 491 + static void solve_2x3(unsigned short m[2][3], unsigned short *coefs) 492 + { 493 + unsigned short minv; 494 + 495 + minv = gf4096_mul(m[1][1], gf4096_inv(m[0][1])); 496 + m[1][0] = m[1][0] ^ gf4096_mul(m[0][0], minv); 497 + m[1][2] = m[1][2] ^ gf4096_mul(m[0][2], minv); 498 + coefs[0] = gf4096_mul(m[1][2], gf4096_inv(m[1][0])); 499 + coefs[1] = gf4096_mul((gf4096_mul(coefs[0], m[0][0]) ^ m[0][2]), gf4096_inv(m[0][1])); 500 + } 501 + 502 + static unsigned char gf64_inv[64] = { 503 + 0, 1, 33, 62, 49, 43, 31, 44, 57, 37, 52, 28, 46, 40, 22, 25, 504 + 61, 54, 51, 39, 26, 35, 14, 24, 23, 15, 20, 34, 11, 53, 45, 6, 505 + 63, 2, 27, 21, 56, 9, 50, 19, 13, 47, 48, 5, 7, 30, 12, 41, 506 + 42, 4, 38, 18, 10, 29, 17, 60, 36, 8, 59, 58, 55, 16, 3, 32 507 + }; 508 + 509 + static unsigned short gf4096_inv(unsigned short din) 510 + { 511 + unsigned short alahxal, ah2B, deno, inv, bl, bh; 512 + unsigned short ah, al, ahxal; 513 + unsigned short dout; 514 + 515 + ah = (din >> 6) & 0x3f; 516 + al = din & 0x3f; 517 + ahxal = ah ^ al; 518 + ah2B = (((ah ^ (ah >> 3)) & 0x1) << 5) | 519 + ((ah >> 1) & 0x10) | 520 + ((((ah >> 5) ^ (ah >> 2)) & 0x1) << 3) | 521 + ((ah >> 2) & 0x4) | ((((ah >> 4) ^ (ah >> 1)) & 0x1) << 1) | (ah & 0x1); 522 + alahxal = gf64_mul(ahxal, al); 523 + deno = alahxal ^ ah2B; 524 + inv = gf64_inv[deno]; 525 + bl = gf64_mul(inv, ahxal); 526 + bh = gf64_mul(inv, ah); 527 + dout = ((bh & 0x3f) << 6) | (bl & 0x3f); 528 + return (((bh & 0x3f) << 6) | (bl & 0x3f)); 529 + } 530 + 531 + static unsigned short err_pos_lut[4096] = { 532 + 0xfff, 0x000, 0x451, 0xfff, 0xfff, 0x3cf, 0xfff, 0x041, 533 + 0xfff, 0xfff, 0xfff, 0xfff, 0x28a, 0xfff, 0x492, 0xfff, 534 + 0x145, 0xfff, 0xfff, 0x514, 0xfff, 0x082, 0xfff, 0xfff, 535 + 0xfff, 0x249, 0x38e, 0x410, 0xfff, 0x104, 0x208, 0x1c7, 536 + 0xfff, 0xfff, 0xfff, 0xfff, 0x2cb, 0xfff, 0xfff, 0xfff, 537 + 0x0c3, 0x34d, 0x4d3, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 538 + 0xfff, 0xfff, 0xfff, 0x186, 0xfff, 0xfff, 0xfff, 0xfff, 539 + 0xfff, 0x30c, 0x555, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 540 + 0xfff, 0xfff, 0xfff, 0x166, 0xfff, 0xfff, 0xfff, 0xfff, 541 + 0x385, 0x14e, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4e1, 542 + 0xfff, 0xfff, 0xfff, 0xfff, 0x538, 0xfff, 0x16d, 0xfff, 543 + 0xfff, 0xfff, 0x45b, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 544 + 0xfff, 0xfff, 0xfff, 0x29c, 0x2cc, 0x30b, 0x2b3, 0xfff, 545 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x0b3, 0xfff, 0x2f7, 546 + 0xfff, 0x32b, 0xfff, 0xfff, 0xfff, 0xfff, 0x0a7, 0xfff, 547 + 0xfff, 0x2da, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 548 + 0xfff, 0x07e, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 549 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x11c, 0xfff, 0xfff, 550 + 0xfff, 0xfff, 0xfff, 0x22f, 0xfff, 0x1f4, 0xfff, 0xfff, 551 + 0x2b0, 0x504, 0xfff, 0x114, 0xfff, 0xfff, 0xfff, 0x21d, 552 + 0xfff, 0xfff, 0xfff, 0xfff, 0x00d, 0x3c4, 0x340, 0x10f, 553 + 0xfff, 0xfff, 0x266, 0x02e, 0xfff, 0xfff, 0xfff, 0x4f8, 554 + 0x337, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 555 + 0xfff, 0xfff, 0xfff, 0x07b, 0x168, 0xfff, 0xfff, 0x0fe, 556 + 0xfff, 0xfff, 0x51a, 0xfff, 0x458, 0xfff, 0x36d, 0xfff, 557 + 0xfff, 0xfff, 0xfff, 0x073, 0x37d, 0x415, 0x550, 0xfff, 558 + 0xfff, 0xfff, 0x23b, 0x4b4, 0xfff, 0xfff, 0xfff, 0x1a1, 559 + 0xfff, 0xfff, 0x3aa, 0xfff, 0x117, 0x04d, 0x341, 0xfff, 560 + 0xfff, 0xfff, 0xfff, 0x518, 0x03e, 0x0f2, 0xfff, 0xfff, 561 + 0xfff, 0xfff, 0xfff, 0x363, 0xfff, 0x0b9, 0xfff, 0xfff, 562 + 0x241, 0xfff, 0xfff, 0x049, 0xfff, 0xfff, 0xfff, 0xfff, 563 + 0x15f, 0x52d, 0xfff, 0xfff, 0xfff, 0x29e, 0xfff, 0xfff, 564 + 0xfff, 0xfff, 0x4cf, 0x0fc, 0xfff, 0x36f, 0x3d3, 0xfff, 565 + 0x228, 0xfff, 0xfff, 0x45e, 0xfff, 0xfff, 0xfff, 0xfff, 566 + 0x238, 0xfff, 0xfff, 0xfff, 0xfff, 0x47f, 0xfff, 0xfff, 567 + 0x43a, 0x265, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x3e8, 568 + 0xfff, 0xfff, 0x01a, 0xfff, 0xfff, 0xfff, 0xfff, 0x21e, 569 + 0x1fc, 0x40b, 0xfff, 0xfff, 0xfff, 0x2d0, 0x159, 0xfff, 570 + 0xfff, 0x313, 0xfff, 0xfff, 0x05c, 0x4cc, 0xfff, 0xfff, 571 + 0x0f6, 0x3d5, 0xfff, 0xfff, 0xfff, 0x54f, 0xfff, 0xfff, 572 + 0xfff, 0x172, 0x1e4, 0x07c, 0xfff, 0xfff, 0xfff, 0xfff, 573 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x53c, 0x1ad, 0x535, 574 + 0x19b, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 575 + 0xfff, 0xfff, 0x092, 0xfff, 0x2be, 0xfff, 0xfff, 0x482, 576 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x0e6, 0xfff, 0xfff, 577 + 0xfff, 0xfff, 0xfff, 0x476, 0xfff, 0x51d, 0xfff, 0xfff, 578 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 579 + 0xfff, 0xfff, 0x342, 0x2b5, 0x22e, 0x09a, 0xfff, 0x08d, 580 + 0x44f, 0x3ed, 0xfff, 0xfff, 0xfff, 0xfff, 0x3d1, 0xfff, 581 + 0xfff, 0x543, 0xfff, 0x48f, 0xfff, 0x3d2, 0xfff, 0x0d5, 582 + 0x113, 0x0ec, 0x427, 0xfff, 0xfff, 0xfff, 0x4c4, 0xfff, 583 + 0xfff, 0x50a, 0xfff, 0x144, 0xfff, 0x105, 0x39f, 0x294, 584 + 0x164, 0xfff, 0x31a, 0xfff, 0xfff, 0x49a, 0xfff, 0x130, 585 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 586 + 0x1be, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 587 + 0xfff, 0xfff, 0x49e, 0x371, 0xfff, 0xfff, 0xfff, 0xfff, 588 + 0xfff, 0xfff, 0xfff, 0xfff, 0x0e8, 0x49c, 0x0f4, 0xfff, 589 + 0x338, 0x1a7, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 590 + 0xfff, 0x36c, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 591 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 592 + 0xfff, 0x1ae, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 593 + 0xfff, 0x31b, 0xfff, 0xfff, 0x2dd, 0x522, 0xfff, 0xfff, 594 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x2f4, 595 + 0x3c6, 0x30d, 0xfff, 0xfff, 0xfff, 0xfff, 0x34c, 0x18f, 596 + 0x30a, 0xfff, 0x01f, 0x079, 0xfff, 0xfff, 0x54d, 0x46b, 597 + 0x28c, 0x37f, 0xfff, 0xfff, 0xfff, 0xfff, 0x355, 0xfff, 598 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x14f, 0xfff, 0xfff, 599 + 0xfff, 0xfff, 0xfff, 0x359, 0x3fe, 0x3c5, 0xfff, 0xfff, 600 + 0xfff, 0xfff, 0x423, 0xfff, 0xfff, 0x34a, 0x22c, 0xfff, 601 + 0x25a, 0xfff, 0xfff, 0x4ad, 0xfff, 0x28d, 0xfff, 0xfff, 602 + 0xfff, 0xfff, 0xfff, 0x547, 0xfff, 0xfff, 0xfff, 0xfff, 603 + 0x2e2, 0xfff, 0xfff, 0x1d5, 0xfff, 0x2a8, 0xfff, 0xfff, 604 + 0x03f, 0xfff, 0xfff, 0xfff, 0xfff, 0x3eb, 0x0fa, 0xfff, 605 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x55b, 0xfff, 606 + 0x08e, 0xfff, 0x3ae, 0xfff, 0x3a4, 0xfff, 0x282, 0x158, 607 + 0xfff, 0x382, 0xfff, 0xfff, 0x499, 0xfff, 0xfff, 0x08a, 608 + 0xfff, 0xfff, 0xfff, 0x456, 0x3be, 0xfff, 0x1e2, 0xfff, 609 + 0xfff, 0xfff, 0xfff, 0xfff, 0x559, 0xfff, 0x1a0, 0xfff, 610 + 0xfff, 0x0b4, 0xfff, 0xfff, 0xfff, 0x2df, 0xfff, 0xfff, 611 + 0xfff, 0x07f, 0x4f5, 0xfff, 0xfff, 0x27c, 0x133, 0x017, 612 + 0xfff, 0x3fd, 0xfff, 0xfff, 0xfff, 0x44d, 0x4cd, 0x17a, 613 + 0x0d7, 0x537, 0xfff, 0xfff, 0x353, 0xfff, 0xfff, 0x351, 614 + 0x366, 0xfff, 0x44a, 0xfff, 0x1a6, 0xfff, 0xfff, 0xfff, 615 + 0x291, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x1e3, 616 + 0xfff, 0xfff, 0xfff, 0xfff, 0x389, 0xfff, 0x07a, 0xfff, 617 + 0x1b6, 0x2ed, 0xfff, 0xfff, 0xfff, 0xfff, 0x24e, 0x074, 618 + 0xfff, 0xfff, 0x3dc, 0xfff, 0x4e3, 0xfff, 0xfff, 0xfff, 619 + 0xfff, 0x4eb, 0xfff, 0xfff, 0x3b8, 0x4de, 0xfff, 0x19c, 620 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x262, 621 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x076, 0x4e8, 0x3da, 622 + 0xfff, 0x531, 0xfff, 0xfff, 0x14a, 0xfff, 0x0a2, 0x433, 623 + 0x3df, 0x1e9, 0xfff, 0xfff, 0xfff, 0xfff, 0x3e7, 0x285, 624 + 0x2d8, 0xfff, 0xfff, 0xfff, 0x349, 0x18d, 0x098, 0xfff, 625 + 0x0df, 0x4bf, 0xfff, 0xfff, 0x0b2, 0xfff, 0x346, 0x24d, 626 + 0xfff, 0xfff, 0xfff, 0x24f, 0x4fa, 0x2f9, 0xfff, 0xfff, 627 + 0x3c9, 0xfff, 0x2b4, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 628 + 0xfff, 0x056, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 629 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 630 + 0xfff, 0x179, 0xfff, 0x0e9, 0x3f0, 0x33d, 0xfff, 0xfff, 631 + 0xfff, 0xfff, 0xfff, 0x1fd, 0xfff, 0xfff, 0x526, 0xfff, 632 + 0xfff, 0xfff, 0x53d, 0xfff, 0xfff, 0xfff, 0x170, 0x331, 633 + 0xfff, 0x068, 0xfff, 0xfff, 0xfff, 0x3f7, 0xfff, 0x3d8, 634 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 635 + 0xfff, 0x09f, 0x556, 0xfff, 0xfff, 0x02d, 0xfff, 0xfff, 636 + 0x553, 0xfff, 0xfff, 0xfff, 0x1f0, 0xfff, 0xfff, 0x4d6, 637 + 0x41e, 0xfff, 0xfff, 0xfff, 0xfff, 0x4d5, 0xfff, 0xfff, 638 + 0xfff, 0xfff, 0xfff, 0x248, 0xfff, 0xfff, 0xfff, 0x0a3, 639 + 0xfff, 0x217, 0xfff, 0xfff, 0xfff, 0x4f1, 0x209, 0xfff, 640 + 0xfff, 0x475, 0x234, 0x52b, 0x398, 0xfff, 0x08b, 0xfff, 641 + 0xfff, 0xfff, 0xfff, 0x2c2, 0xfff, 0xfff, 0xfff, 0xfff, 642 + 0xfff, 0xfff, 0x268, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 643 + 0xfff, 0x4a3, 0xfff, 0x0aa, 0xfff, 0x1d9, 0xfff, 0xfff, 644 + 0xfff, 0xfff, 0x155, 0xfff, 0xfff, 0xfff, 0xfff, 0x0bf, 645 + 0x539, 0xfff, 0xfff, 0x2f1, 0x545, 0xfff, 0xfff, 0xfff, 646 + 0xfff, 0xfff, 0xfff, 0x2a7, 0x06f, 0xfff, 0x378, 0xfff, 647 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x25e, 0xfff, 648 + 0xfff, 0xfff, 0xfff, 0x15d, 0x02a, 0xfff, 0xfff, 0x0bc, 649 + 0x235, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 650 + 0x150, 0xfff, 0x1a9, 0xfff, 0xfff, 0xfff, 0xfff, 0x381, 651 + 0xfff, 0x04e, 0x270, 0x13f, 0xfff, 0xfff, 0x405, 0xfff, 652 + 0x3cd, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 653 + 0xfff, 0x2ef, 0xfff, 0x06a, 0xfff, 0xfff, 0xfff, 0x34f, 654 + 0x212, 0xfff, 0xfff, 0x0e2, 0xfff, 0x083, 0x298, 0xfff, 655 + 0xfff, 0xfff, 0x0c2, 0xfff, 0xfff, 0x52e, 0xfff, 0x488, 656 + 0xfff, 0xfff, 0xfff, 0x36b, 0xfff, 0xfff, 0xfff, 0x442, 657 + 0x091, 0xfff, 0x41c, 0xfff, 0xfff, 0x3a5, 0xfff, 0x4e6, 658 + 0xfff, 0xfff, 0x40d, 0x31d, 0xfff, 0xfff, 0xfff, 0x4c1, 659 + 0x053, 0xfff, 0x418, 0x13c, 0xfff, 0x350, 0xfff, 0x0ae, 660 + 0xfff, 0xfff, 0x41f, 0xfff, 0x470, 0xfff, 0x4ca, 0xfff, 661 + 0xfff, 0xfff, 0x02b, 0x450, 0xfff, 0x1f8, 0xfff, 0xfff, 662 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x293, 0xfff, 663 + 0xfff, 0xfff, 0xfff, 0x411, 0xfff, 0xfff, 0xfff, 0xfff, 664 + 0xfff, 0xfff, 0xfff, 0xfff, 0x0b8, 0xfff, 0xfff, 0xfff, 665 + 0x3e1, 0xfff, 0xfff, 0xfff, 0xfff, 0x43c, 0xfff, 0x2b2, 666 + 0x2ab, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x1ec, 667 + 0xfff, 0xfff, 0xfff, 0x3f8, 0x034, 0xfff, 0xfff, 0xfff, 668 + 0xfff, 0xfff, 0xfff, 0x11a, 0xfff, 0x541, 0x45c, 0x134, 669 + 0x1cc, 0xfff, 0xfff, 0xfff, 0x469, 0xfff, 0xfff, 0x44b, 670 + 0x161, 0xfff, 0xfff, 0xfff, 0x055, 0xfff, 0xfff, 0xfff, 671 + 0xfff, 0x307, 0xfff, 0xfff, 0xfff, 0xfff, 0x2d1, 0xfff, 672 + 0xfff, 0xfff, 0x124, 0x37b, 0x26b, 0x336, 0xfff, 0xfff, 673 + 0x2e4, 0x3cb, 0xfff, 0xfff, 0x0f8, 0x3c8, 0xfff, 0xfff, 674 + 0xfff, 0x461, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4b5, 675 + 0x2cf, 0xfff, 0xfff, 0xfff, 0x20f, 0xfff, 0x35a, 0xfff, 676 + 0x490, 0xfff, 0x185, 0xfff, 0xfff, 0xfff, 0xfff, 0x42e, 677 + 0xfff, 0xfff, 0xfff, 0xfff, 0x54b, 0xfff, 0xfff, 0xfff, 678 + 0x146, 0xfff, 0x412, 0xfff, 0xfff, 0xfff, 0x1ff, 0xfff, 679 + 0xfff, 0x3e0, 0xfff, 0xfff, 0xfff, 0xfff, 0x2d5, 0xfff, 680 + 0x4df, 0x505, 0xfff, 0x413, 0xfff, 0x1a5, 0xfff, 0x3b2, 681 + 0xfff, 0xfff, 0xfff, 0x35b, 0xfff, 0x116, 0xfff, 0xfff, 682 + 0x171, 0x4d0, 0xfff, 0x154, 0x12d, 0xfff, 0xfff, 0xfff, 683 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x468, 0x4db, 0xfff, 684 + 0xfff, 0x1df, 0xfff, 0xfff, 0xfff, 0xfff, 0x05a, 0xfff, 685 + 0x0f1, 0x403, 0xfff, 0x22b, 0x2e0, 0xfff, 0xfff, 0xfff, 686 + 0x2b7, 0x373, 0xfff, 0xfff, 0xfff, 0xfff, 0x13e, 0xfff, 687 + 0xfff, 0xfff, 0x0d0, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 688 + 0x329, 0x1d2, 0x3fa, 0x047, 0xfff, 0x2f2, 0xfff, 0xfff, 689 + 0x141, 0x0ac, 0x1d7, 0xfff, 0x07d, 0xfff, 0xfff, 0xfff, 690 + 0x1c1, 0xfff, 0x487, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 691 + 0xfff, 0xfff, 0xfff, 0x045, 0xfff, 0xfff, 0xfff, 0xfff, 692 + 0x288, 0x0cd, 0xfff, 0xfff, 0xfff, 0xfff, 0x226, 0x1d8, 693 + 0xfff, 0x153, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4cb, 694 + 0x528, 0xfff, 0xfff, 0xfff, 0x20a, 0x343, 0x3a1, 0xfff, 695 + 0xfff, 0xfff, 0x2d7, 0x2d3, 0x1aa, 0x4c5, 0xfff, 0xfff, 696 + 0xfff, 0x42b, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 697 + 0xfff, 0xfff, 0xfff, 0xfff, 0x3e9, 0xfff, 0x20b, 0x260, 698 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x37c, 0x2fd, 699 + 0xfff, 0xfff, 0x2c8, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 700 + 0xfff, 0x31e, 0xfff, 0x335, 0xfff, 0xfff, 0xfff, 0xfff, 701 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 702 + 0xfff, 0xfff, 0x135, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 703 + 0xfff, 0xfff, 0x35c, 0x4dd, 0x129, 0xfff, 0xfff, 0xfff, 704 + 0xfff, 0xfff, 0x1ef, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 705 + 0xfff, 0x34e, 0xfff, 0xfff, 0xfff, 0xfff, 0x407, 0xfff, 706 + 0xfff, 0xfff, 0xfff, 0xfff, 0x3ad, 0xfff, 0xfff, 0xfff, 707 + 0x379, 0xfff, 0xfff, 0x1d0, 0x38d, 0xfff, 0xfff, 0x1e8, 708 + 0x184, 0x3c1, 0x1c4, 0xfff, 0x1f9, 0xfff, 0xfff, 0x424, 709 + 0xfff, 0xfff, 0xfff, 0xfff, 0x1d3, 0x0d4, 0xfff, 0x4e9, 710 + 0xfff, 0xfff, 0xfff, 0x530, 0x107, 0xfff, 0x106, 0x04f, 711 + 0xfff, 0xfff, 0x4c7, 0x503, 0xfff, 0xfff, 0xfff, 0xfff, 712 + 0xfff, 0x15c, 0xfff, 0x23f, 0xfff, 0xfff, 0xfff, 0xfff, 713 + 0xfff, 0xfff, 0xfff, 0xfff, 0x4f3, 0xfff, 0xfff, 0x3c7, 714 + 0xfff, 0x278, 0xfff, 0xfff, 0x0a6, 0xfff, 0xfff, 0xfff, 715 + 0x122, 0x1cf, 0xfff, 0x327, 0xfff, 0x2e5, 0xfff, 0x29d, 716 + 0xfff, 0xfff, 0x3f1, 0xfff, 0xfff, 0x48d, 0xfff, 0xfff, 717 + 0xfff, 0xfff, 0x054, 0xfff, 0xfff, 0xfff, 0xfff, 0x178, 718 + 0x27e, 0x4e0, 0x352, 0x02f, 0x09c, 0xfff, 0x2a0, 0xfff, 719 + 0xfff, 0x46a, 0x457, 0xfff, 0xfff, 0x501, 0xfff, 0x2ba, 720 + 0xfff, 0xfff, 0xfff, 0x54e, 0x2e7, 0xfff, 0xfff, 0xfff, 721 + 0xfff, 0xfff, 0x551, 0xfff, 0xfff, 0x1db, 0x2aa, 0xfff, 722 + 0xfff, 0x4bc, 0xfff, 0xfff, 0x395, 0xfff, 0x0de, 0xfff, 723 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x455, 0xfff, 0x17e, 724 + 0xfff, 0x221, 0x4a7, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 725 + 0x388, 0xfff, 0xfff, 0xfff, 0x308, 0xfff, 0xfff, 0xfff, 726 + 0x20e, 0x4b9, 0xfff, 0x273, 0x20c, 0x09e, 0xfff, 0x057, 727 + 0xfff, 0xfff, 0xfff, 0xfff, 0x3f2, 0xfff, 0x1a8, 0x3a6, 728 + 0x14c, 0xfff, 0xfff, 0x071, 0xfff, 0xfff, 0x53a, 0xfff, 729 + 0xfff, 0xfff, 0xfff, 0x109, 0xfff, 0xfff, 0x399, 0xfff, 730 + 0x061, 0x4f0, 0x39e, 0x244, 0xfff, 0x035, 0xfff, 0xfff, 731 + 0x305, 0x47e, 0x297, 0xfff, 0xfff, 0x2b8, 0xfff, 0xfff, 732 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x1bc, 0xfff, 0x2fc, 733 + 0xfff, 0xfff, 0x554, 0xfff, 0xfff, 0xfff, 0xfff, 0x3b6, 734 + 0xfff, 0xfff, 0xfff, 0x515, 0x397, 0xfff, 0xfff, 0x12f, 735 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4e5, 736 + 0xfff, 0x4fc, 0xfff, 0xfff, 0x05e, 0xfff, 0xfff, 0xfff, 737 + 0xfff, 0xfff, 0x0a8, 0x3af, 0x015, 0xfff, 0xfff, 0xfff, 738 + 0xfff, 0x138, 0xfff, 0xfff, 0xfff, 0x540, 0xfff, 0xfff, 739 + 0xfff, 0x027, 0x523, 0x2f0, 0xfff, 0xfff, 0xfff, 0xfff, 740 + 0xfff, 0xfff, 0x16c, 0xfff, 0x27d, 0xfff, 0xfff, 0xfff, 741 + 0xfff, 0x04c, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4dc, 742 + 0xfff, 0xfff, 0x059, 0x301, 0xfff, 0xfff, 0xfff, 0xfff, 743 + 0xfff, 0xfff, 0xfff, 0x1a3, 0xfff, 0x15a, 0xfff, 0xfff, 744 + 0x0a5, 0xfff, 0x435, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 745 + 0xfff, 0x051, 0xfff, 0xfff, 0x131, 0xfff, 0x4f4, 0xfff, 746 + 0xfff, 0xfff, 0xfff, 0x441, 0xfff, 0x4fb, 0xfff, 0x03b, 747 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x1ed, 0x274, 748 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x0d3, 0x55e, 0x1b3, 749 + 0xfff, 0x0bd, 0xfff, 0xfff, 0xfff, 0xfff, 0x225, 0xfff, 750 + 0xfff, 0xfff, 0xfff, 0xfff, 0x4b7, 0xfff, 0xfff, 0x2ff, 751 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4c3, 0xfff, 752 + 0x383, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x2f6, 753 + 0xfff, 0xfff, 0x1ee, 0xfff, 0x03d, 0xfff, 0xfff, 0xfff, 754 + 0xfff, 0xfff, 0x26f, 0x1dc, 0xfff, 0x0db, 0xfff, 0xfff, 755 + 0xfff, 0xfff, 0xfff, 0x0ce, 0xfff, 0xfff, 0x127, 0x03a, 756 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x311, 0xfff, 757 + 0xfff, 0x13d, 0x09d, 0x47b, 0x2a6, 0x50d, 0x510, 0x19a, 758 + 0xfff, 0x354, 0x414, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 759 + 0xfff, 0xfff, 0x44c, 0x3b0, 0xfff, 0x23d, 0x429, 0xfff, 760 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 761 + 0x4c0, 0x416, 0xfff, 0x05b, 0xfff, 0xfff, 0x137, 0xfff, 762 + 0x25f, 0x49f, 0xfff, 0x279, 0x013, 0xfff, 0xfff, 0xfff, 763 + 0x269, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 764 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x3d0, 0xfff, 0xfff, 765 + 0xfff, 0xfff, 0xfff, 0xfff, 0x077, 0xfff, 0xfff, 0x3fb, 766 + 0xfff, 0xfff, 0xfff, 0xfff, 0x271, 0x3a0, 0xfff, 0xfff, 767 + 0x40f, 0xfff, 0xfff, 0x3de, 0xfff, 0xfff, 0xfff, 0xfff, 768 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x1ab, 0x26a, 769 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x489, 0xfff, 0xfff, 770 + 0x252, 0xfff, 0xfff, 0xfff, 0xfff, 0x1b7, 0x42f, 0xfff, 771 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x3b7, 772 + 0xfff, 0x2bb, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 773 + 0xfff, 0xfff, 0xfff, 0x0f7, 0x01d, 0xfff, 0x067, 0xfff, 774 + 0xfff, 0xfff, 0xfff, 0x4e2, 0xfff, 0xfff, 0x4bb, 0xfff, 775 + 0xfff, 0xfff, 0x17b, 0xfff, 0x0ee, 0xfff, 0xfff, 0xfff, 776 + 0xfff, 0xfff, 0x36e, 0xfff, 0xfff, 0xfff, 0x533, 0xfff, 777 + 0xfff, 0xfff, 0x4d4, 0x356, 0xfff, 0xfff, 0x375, 0xfff, 778 + 0xfff, 0xfff, 0xfff, 0x4a4, 0x513, 0xfff, 0xfff, 0xfff, 779 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4ff, 0xfff, 0x2af, 780 + 0xfff, 0xfff, 0x026, 0xfff, 0x0ad, 0xfff, 0xfff, 0xfff, 781 + 0xfff, 0x26e, 0xfff, 0xfff, 0xfff, 0xfff, 0x493, 0xfff, 782 + 0x463, 0x4d2, 0x4be, 0xfff, 0xfff, 0xfff, 0xfff, 0x4f2, 783 + 0x0b6, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 784 + 0xfff, 0x32d, 0x315, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 785 + 0xfff, 0x13a, 0x4a1, 0xfff, 0x27a, 0xfff, 0xfff, 0xfff, 786 + 0x47a, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 787 + 0x334, 0xfff, 0xfff, 0xfff, 0xfff, 0x54c, 0xfff, 0xfff, 788 + 0xfff, 0x0c9, 0x007, 0xfff, 0xfff, 0x12e, 0xfff, 0x0ff, 789 + 0xfff, 0xfff, 0x3f5, 0x509, 0xfff, 0xfff, 0xfff, 0xfff, 790 + 0x1c3, 0x2ad, 0xfff, 0xfff, 0x47c, 0x261, 0xfff, 0xfff, 791 + 0xfff, 0xfff, 0xfff, 0x152, 0xfff, 0xfff, 0xfff, 0x339, 792 + 0xfff, 0x243, 0x1c0, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 793 + 0x063, 0xfff, 0xfff, 0x254, 0xfff, 0xfff, 0x173, 0xfff, 794 + 0x0c7, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 795 + 0xfff, 0x362, 0x259, 0x485, 0x374, 0x0dc, 0x3ab, 0xfff, 796 + 0x1c5, 0x534, 0x544, 0xfff, 0xfff, 0x508, 0xfff, 0x402, 797 + 0x408, 0xfff, 0x0e7, 0xfff, 0xfff, 0x00a, 0x205, 0xfff, 798 + 0xfff, 0x2b9, 0xfff, 0xfff, 0xfff, 0x465, 0xfff, 0xfff, 799 + 0xfff, 0xfff, 0xfff, 0xfff, 0x23a, 0xfff, 0xfff, 0xfff, 800 + 0xfff, 0x147, 0x19d, 0x115, 0x214, 0xfff, 0x090, 0x368, 801 + 0xfff, 0x210, 0xfff, 0xfff, 0x280, 0x52a, 0x163, 0x148, 802 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x326, 0xfff, 0xfff, 803 + 0xfff, 0xfff, 0xfff, 0x2de, 0xfff, 0xfff, 0xfff, 0xfff, 804 + 0x206, 0x2c1, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 805 + 0x189, 0xfff, 0xfff, 0xfff, 0xfff, 0x367, 0xfff, 0x1a4, 806 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x443, 0xfff, 0x27b, 807 + 0xfff, 0xfff, 0x251, 0x549, 0xfff, 0xfff, 0xfff, 0xfff, 808 + 0xfff, 0xfff, 0x188, 0x04b, 0xfff, 0xfff, 0xfff, 0x31f, 809 + 0x4a6, 0xfff, 0x246, 0x1de, 0x156, 0xfff, 0xfff, 0xfff, 810 + 0x3a9, 0xfff, 0xfff, 0xfff, 0x2fa, 0xfff, 0x128, 0x0d1, 811 + 0x449, 0x255, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 812 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 813 + 0xfff, 0xfff, 0xfff, 0xfff, 0x258, 0xfff, 0xfff, 0xfff, 814 + 0x532, 0xfff, 0xfff, 0xfff, 0x303, 0x517, 0xfff, 0xfff, 815 + 0x2a9, 0x24a, 0xfff, 0xfff, 0x231, 0xfff, 0xfff, 0xfff, 816 + 0xfff, 0xfff, 0x4b6, 0x516, 0xfff, 0xfff, 0x0e4, 0x0eb, 817 + 0xfff, 0x4e4, 0xfff, 0x275, 0xfff, 0xfff, 0x031, 0xfff, 818 + 0xfff, 0xfff, 0xfff, 0xfff, 0x025, 0x21a, 0xfff, 0x0cc, 819 + 0x45f, 0x3d9, 0x289, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 820 + 0xfff, 0xfff, 0x23e, 0xfff, 0xfff, 0xfff, 0x438, 0x097, 821 + 0x419, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 822 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 823 + 0xfff, 0xfff, 0x0a9, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 824 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 825 + 0x37e, 0x0e0, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x431, 826 + 0x372, 0xfff, 0xfff, 0xfff, 0x1ba, 0x06e, 0xfff, 0x1b1, 827 + 0xfff, 0xfff, 0x12a, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 828 + 0xfff, 0xfff, 0x193, 0xfff, 0xfff, 0xfff, 0xfff, 0x10a, 829 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x048, 0x1b4, 830 + 0xfff, 0xfff, 0xfff, 0xfff, 0x295, 0x140, 0x108, 0xfff, 831 + 0xfff, 0xfff, 0xfff, 0x16f, 0xfff, 0x0a4, 0x37a, 0xfff, 832 + 0x29a, 0xfff, 0x284, 0xfff, 0xfff, 0xfff, 0xfff, 0x4c6, 833 + 0x2a2, 0x3a3, 0xfff, 0x201, 0xfff, 0xfff, 0xfff, 0x4bd, 834 + 0x005, 0x54a, 0x3b5, 0x204, 0x2ee, 0x11d, 0x436, 0xfff, 835 + 0xfff, 0xfff, 0xfff, 0xfff, 0x3ec, 0xfff, 0xfff, 0xfff, 836 + 0xfff, 0xfff, 0xfff, 0xfff, 0x11f, 0x498, 0x21c, 0xfff, 837 + 0xfff, 0xfff, 0x3d6, 0xfff, 0x4ab, 0xfff, 0x432, 0x2eb, 838 + 0x542, 0x4fd, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 839 + 0xfff, 0xfff, 0xfff, 0x4ce, 0xfff, 0xfff, 0x2fb, 0xfff, 840 + 0xfff, 0x2e1, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 841 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x1b9, 0x037, 0x0dd, 842 + 0xfff, 0xfff, 0xfff, 0x2bf, 0x521, 0x496, 0x095, 0xfff, 843 + 0xfff, 0x328, 0x070, 0x1bf, 0xfff, 0x393, 0xfff, 0xfff, 844 + 0x102, 0xfff, 0xfff, 0x21b, 0xfff, 0x142, 0x263, 0x519, 845 + 0xfff, 0x2a5, 0x177, 0xfff, 0x14d, 0x471, 0x4ae, 0xfff, 846 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 847 + 0x1f6, 0xfff, 0x481, 0xfff, 0xfff, 0xfff, 0x151, 0xfff, 848 + 0xfff, 0xfff, 0x085, 0x33f, 0xfff, 0xfff, 0xfff, 0x084, 849 + 0xfff, 0xfff, 0xfff, 0x345, 0x3a2, 0xfff, 0xfff, 0x0a0, 850 + 0x0da, 0x024, 0xfff, 0xfff, 0xfff, 0x1bd, 0xfff, 0x55c, 851 + 0x467, 0x445, 0xfff, 0xfff, 0xfff, 0x052, 0xfff, 0xfff, 852 + 0xfff, 0xfff, 0x51e, 0xfff, 0xfff, 0x39d, 0xfff, 0x35f, 853 + 0xfff, 0x376, 0x3ee, 0xfff, 0xfff, 0xfff, 0xfff, 0x448, 854 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x16a, 855 + 0xfff, 0x036, 0x38f, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 856 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x211, 857 + 0xfff, 0xfff, 0xfff, 0x230, 0xfff, 0xfff, 0x3ba, 0xfff, 858 + 0xfff, 0xfff, 0x3ce, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 859 + 0xfff, 0xfff, 0xfff, 0x229, 0xfff, 0x176, 0xfff, 0xfff, 860 + 0xfff, 0xfff, 0xfff, 0x00b, 0xfff, 0x162, 0x018, 0xfff, 861 + 0xfff, 0x233, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 862 + 0x400, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 863 + 0xfff, 0xfff, 0xfff, 0x12b, 0xfff, 0xfff, 0xfff, 0xfff, 864 + 0xfff, 0x3f4, 0xfff, 0x0f0, 0xfff, 0x1ac, 0xfff, 0xfff, 865 + 0x119, 0xfff, 0x2c0, 0xfff, 0xfff, 0xfff, 0x49b, 0xfff, 866 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x23c, 0xfff, 867 + 0x4b3, 0x010, 0x064, 0xfff, 0xfff, 0x4ba, 0xfff, 0xfff, 868 + 0xfff, 0xfff, 0xfff, 0x3c2, 0xfff, 0xfff, 0xfff, 0xfff, 869 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x006, 0x196, 0xfff, 870 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x100, 0x191, 0xfff, 871 + 0x1ea, 0x29f, 0xfff, 0xfff, 0xfff, 0x276, 0xfff, 0xfff, 872 + 0x2b1, 0x3b9, 0xfff, 0x03c, 0xfff, 0xfff, 0xfff, 0x180, 873 + 0xfff, 0x08f, 0xfff, 0xfff, 0x19e, 0x019, 0xfff, 0x0b0, 874 + 0x0fd, 0x332, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 875 + 0xfff, 0x06b, 0x2e8, 0xfff, 0x446, 0xfff, 0xfff, 0x004, 876 + 0x247, 0x197, 0xfff, 0x112, 0x169, 0x292, 0xfff, 0x302, 877 + 0xfff, 0xfff, 0x33b, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 878 + 0xfff, 0xfff, 0xfff, 0x287, 0x21f, 0xfff, 0x3ea, 0xfff, 879 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4e7, 0xfff, 0xfff, 880 + 0xfff, 0xfff, 0xfff, 0x3a8, 0xfff, 0xfff, 0x2bc, 0xfff, 881 + 0x484, 0x296, 0xfff, 0x1c9, 0x08c, 0x1e5, 0x48a, 0xfff, 882 + 0x360, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 883 + 0x1ca, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 884 + 0xfff, 0xfff, 0xfff, 0x10d, 0xfff, 0xfff, 0xfff, 0xfff, 885 + 0xfff, 0xfff, 0x066, 0x2ea, 0x28b, 0x25b, 0xfff, 0x072, 886 + 0xfff, 0xfff, 0xfff, 0xfff, 0x2b6, 0xfff, 0xfff, 0x272, 887 + 0xfff, 0xfff, 0x525, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 888 + 0x2ca, 0xfff, 0xfff, 0xfff, 0x299, 0xfff, 0xfff, 0xfff, 889 + 0x558, 0x41a, 0xfff, 0x4f7, 0x557, 0xfff, 0x4a0, 0x344, 890 + 0x12c, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x125, 891 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 892 + 0x40e, 0xfff, 0xfff, 0x502, 0xfff, 0x103, 0x3e6, 0xfff, 893 + 0x527, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 894 + 0xfff, 0xfff, 0xfff, 0x45d, 0xfff, 0xfff, 0xfff, 0xfff, 895 + 0x44e, 0xfff, 0xfff, 0xfff, 0xfff, 0x0d2, 0x4c9, 0x35e, 896 + 0x459, 0x2d9, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x17d, 897 + 0x0c4, 0xfff, 0xfff, 0xfff, 0x3ac, 0x390, 0x094, 0xfff, 898 + 0x483, 0x0ab, 0xfff, 0x253, 0xfff, 0x391, 0xfff, 0xfff, 899 + 0xfff, 0xfff, 0x123, 0x0ef, 0xfff, 0xfff, 0xfff, 0x330, 900 + 0x38c, 0xfff, 0xfff, 0x2ae, 0xfff, 0xfff, 0xfff, 0x042, 901 + 0x012, 0x06d, 0xfff, 0xfff, 0xfff, 0x32a, 0x3db, 0x364, 902 + 0x2dc, 0xfff, 0x30f, 0x3d7, 0x4a5, 0x050, 0xfff, 0xfff, 903 + 0x029, 0xfff, 0xfff, 0xfff, 0xfff, 0x1d1, 0xfff, 0xfff, 904 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x480, 0xfff, 905 + 0x4ed, 0x081, 0x0a1, 0xfff, 0xfff, 0xfff, 0x30e, 0x52f, 906 + 0x257, 0xfff, 0xfff, 0x447, 0xfff, 0xfff, 0xfff, 0xfff, 907 + 0xfff, 0xfff, 0xfff, 0x401, 0x3cc, 0xfff, 0xfff, 0x0fb, 908 + 0x2c9, 0x42a, 0x314, 0x33e, 0x3bd, 0x318, 0xfff, 0x10e, 909 + 0x2a1, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x24c, 910 + 0x506, 0xfff, 0x267, 0xfff, 0xfff, 0x219, 0xfff, 0x1eb, 911 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 912 + 0x309, 0x3e2, 0x46c, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 913 + 0x384, 0xfff, 0xfff, 0xfff, 0xfff, 0x50c, 0xfff, 0x24b, 914 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x038, 915 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x194, 916 + 0x143, 0x3e3, 0xfff, 0xfff, 0xfff, 0x4c2, 0xfff, 0xfff, 917 + 0x0e1, 0x25c, 0xfff, 0x237, 0xfff, 0x1fe, 0xfff, 0xfff, 918 + 0xfff, 0x065, 0x2a4, 0xfff, 0x386, 0x55a, 0x11b, 0xfff, 919 + 0xfff, 0x192, 0xfff, 0x183, 0x00e, 0xfff, 0xfff, 0xfff, 920 + 0xfff, 0xfff, 0xfff, 0x4b2, 0x18e, 0xfff, 0xfff, 0xfff, 921 + 0xfff, 0x486, 0x4ef, 0x0c6, 0x380, 0xfff, 0x4a8, 0xfff, 922 + 0x0c5, 0xfff, 0xfff, 0xfff, 0xfff, 0x093, 0x1b8, 0xfff, 923 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x2e6, 924 + 0xfff, 0x0f3, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 925 + 0x28e, 0xfff, 0x53b, 0x420, 0x22a, 0x33a, 0xfff, 0x387, 926 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x2a3, 0xfff, 0xfff, 927 + 0xfff, 0x428, 0x500, 0xfff, 0xfff, 0x120, 0x2c6, 0x290, 928 + 0x2f5, 0x0e3, 0xfff, 0x0b7, 0xfff, 0x319, 0x474, 0xfff, 929 + 0xfff, 0xfff, 0x529, 0x014, 0xfff, 0x41b, 0x40a, 0x18b, 930 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x0d9, 931 + 0xfff, 0x38a, 0xfff, 0xfff, 0xfff, 0xfff, 0x1ce, 0xfff, 932 + 0xfff, 0xfff, 0xfff, 0xfff, 0x3b1, 0xfff, 0xfff, 0x05d, 933 + 0x2c4, 0xfff, 0xfff, 0x4af, 0xfff, 0x030, 0xfff, 0xfff, 934 + 0x203, 0xfff, 0x277, 0x256, 0xfff, 0xfff, 0xfff, 0x4f9, 935 + 0xfff, 0x2c7, 0xfff, 0x466, 0x016, 0x1cd, 0xfff, 0x167, 936 + 0xfff, 0xfff, 0x0c8, 0xfff, 0x43d, 0xfff, 0xfff, 0x020, 937 + 0xfff, 0xfff, 0x232, 0x1cb, 0x1e0, 0xfff, 0xfff, 0x347, 938 + 0xfff, 0x478, 0xfff, 0x365, 0xfff, 0xfff, 0xfff, 0xfff, 939 + 0x358, 0xfff, 0x10b, 0xfff, 0x35d, 0xfff, 0xfff, 0xfff, 940 + 0xfff, 0xfff, 0x452, 0x22d, 0xfff, 0xfff, 0x47d, 0xfff, 941 + 0x2f3, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x460, 0xfff, 942 + 0xfff, 0xfff, 0x50b, 0xfff, 0xfff, 0xfff, 0x2ec, 0xfff, 943 + 0xfff, 0xfff, 0xfff, 0xfff, 0x4b1, 0x422, 0xfff, 0xfff, 944 + 0xfff, 0x2d4, 0xfff, 0x239, 0xfff, 0xfff, 0xfff, 0x439, 945 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 946 + 0xfff, 0x491, 0x075, 0xfff, 0xfff, 0xfff, 0x06c, 0xfff, 947 + 0xfff, 0x0f9, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 948 + 0xfff, 0x139, 0xfff, 0x4f6, 0xfff, 0xfff, 0x409, 0xfff, 949 + 0xfff, 0x15b, 0xfff, 0xfff, 0x348, 0xfff, 0xfff, 0xfff, 950 + 0xfff, 0x4a2, 0x49d, 0xfff, 0x033, 0x175, 0xfff, 0x039, 951 + 0xfff, 0x312, 0x40c, 0xfff, 0xfff, 0x325, 0xfff, 0xfff, 952 + 0xfff, 0xfff, 0xfff, 0xfff, 0x4aa, 0xfff, 0xfff, 0xfff, 953 + 0xfff, 0xfff, 0xfff, 0x165, 0x3bc, 0x48c, 0x310, 0x096, 954 + 0xfff, 0xfff, 0x250, 0x1a2, 0xfff, 0xfff, 0xfff, 0xfff, 955 + 0x20d, 0x2ac, 0xfff, 0xfff, 0x39b, 0xfff, 0x377, 0xfff, 956 + 0x512, 0x495, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 957 + 0xfff, 0xfff, 0xfff, 0xfff, 0x357, 0x4ea, 0xfff, 0xfff, 958 + 0xfff, 0xfff, 0x198, 0xfff, 0xfff, 0xfff, 0x434, 0x04a, 959 + 0xfff, 0xfff, 0xfff, 0xfff, 0x062, 0xfff, 0x1d6, 0x1c8, 960 + 0xfff, 0x1f3, 0x281, 0xfff, 0x462, 0xfff, 0xfff, 0xfff, 961 + 0x4b0, 0xfff, 0x207, 0xfff, 0xfff, 0xfff, 0xfff, 0x3dd, 962 + 0xfff, 0xfff, 0x55d, 0xfff, 0x552, 0x494, 0x1af, 0xfff, 963 + 0xfff, 0xfff, 0xfff, 0xfff, 0x227, 0xfff, 0xfff, 0x069, 964 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x43e, 965 + 0x0b5, 0xfff, 0x524, 0x2d2, 0xfff, 0xfff, 0xfff, 0x28f, 966 + 0xfff, 0x01b, 0x50e, 0xfff, 0xfff, 0x1bb, 0xfff, 0xfff, 967 + 0x41d, 0xfff, 0x32e, 0x48e, 0xfff, 0x1f7, 0x224, 0xfff, 968 + 0xfff, 0xfff, 0xfff, 0xfff, 0x394, 0xfff, 0xfff, 0xfff, 969 + 0xfff, 0x52c, 0xfff, 0xfff, 0xfff, 0x392, 0xfff, 0x1e7, 970 + 0xfff, 0xfff, 0x3f9, 0x3a7, 0xfff, 0x51f, 0xfff, 0x0bb, 971 + 0x118, 0x3ca, 0xfff, 0x1dd, 0xfff, 0x48b, 0xfff, 0xfff, 972 + 0xfff, 0xfff, 0x50f, 0xfff, 0x0d6, 0xfff, 0x1fa, 0xfff, 973 + 0x11e, 0xfff, 0xfff, 0xfff, 0xfff, 0x4d7, 0xfff, 0x078, 974 + 0x008, 0xfff, 0x25d, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 975 + 0x032, 0x33c, 0xfff, 0x4d9, 0x160, 0xfff, 0xfff, 0x300, 976 + 0x0b1, 0xfff, 0x322, 0xfff, 0x4ec, 0xfff, 0xfff, 0x200, 977 + 0x00c, 0x369, 0x473, 0xfff, 0xfff, 0x32c, 0xfff, 0xfff, 978 + 0xfff, 0xfff, 0xfff, 0xfff, 0x53e, 0x3d4, 0x417, 0xfff, 979 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 980 + 0x34b, 0x001, 0x39a, 0x02c, 0xfff, 0xfff, 0x2ce, 0x00f, 981 + 0xfff, 0x0ba, 0xfff, 0xfff, 0xfff, 0xfff, 0x060, 0xfff, 982 + 0x406, 0xfff, 0xfff, 0xfff, 0x4ee, 0x4ac, 0xfff, 0x43f, 983 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x29b, 0xfff, 0xfff, 984 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x216, 985 + 0x190, 0xfff, 0x396, 0x464, 0xfff, 0xfff, 0x323, 0xfff, 986 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x2e9, 0xfff, 0x26d, 987 + 0x2cd, 0x040, 0xfff, 0xfff, 0xfff, 0xfff, 0x38b, 0x3c0, 988 + 0xfff, 0xfff, 0xfff, 0x1f2, 0xfff, 0x0ea, 0xfff, 0xfff, 989 + 0x472, 0xfff, 0x1fb, 0xfff, 0xfff, 0x0af, 0x27f, 0xfff, 990 + 0xfff, 0xfff, 0x479, 0x023, 0xfff, 0x0d8, 0x3b3, 0xfff, 991 + 0xfff, 0xfff, 0x121, 0xfff, 0xfff, 0x3bf, 0xfff, 0xfff, 992 + 0x16b, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 993 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 994 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 995 + 0x45a, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 996 + 0xfff, 0x0be, 0xfff, 0xfff, 0xfff, 0x111, 0xfff, 0x220, 997 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 998 + 0xfff, 0xfff, 0x09b, 0x218, 0xfff, 0x022, 0x202, 0xfff, 999 + 0x4c8, 0xfff, 0x0ed, 0xfff, 0xfff, 0x182, 0xfff, 0xfff, 1000 + 0xfff, 0x17f, 0x213, 0xfff, 0x321, 0x36a, 0xfff, 0x086, 1001 + 0xfff, 0xfff, 0xfff, 0x43b, 0x088, 0xfff, 0xfff, 0xfff, 1002 + 0xfff, 0x26c, 0xfff, 0x2f8, 0x3b4, 0xfff, 0xfff, 0xfff, 1003 + 0x132, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x333, 0x444, 1004 + 0x0c1, 0x4d8, 0x46d, 0x264, 0xfff, 0xfff, 0xfff, 0xfff, 1005 + 0x426, 0xfff, 0xfff, 0xfff, 0xfff, 0x2fe, 0xfff, 0xfff, 1006 + 0xfff, 0xfff, 0x011, 0xfff, 0x05f, 0xfff, 0xfff, 0xfff, 1007 + 0xfff, 0x10c, 0x101, 0xfff, 0xfff, 0xfff, 0xfff, 0x110, 1008 + 0xfff, 0x044, 0x304, 0x361, 0x404, 0xfff, 0x51b, 0x099, 1009 + 0xfff, 0x440, 0xfff, 0xfff, 0xfff, 0x222, 0xfff, 0xfff, 1010 + 0xfff, 0xfff, 0x1b5, 0xfff, 0x136, 0x430, 0xfff, 0x1da, 1011 + 0xfff, 0xfff, 0xfff, 0x043, 0xfff, 0x17c, 0xfff, 0xfff, 1012 + 0xfff, 0x01c, 0xfff, 0xfff, 0xfff, 0x425, 0x236, 0xfff, 1013 + 0x317, 0xfff, 0xfff, 0x437, 0x3fc, 0xfff, 0x1f1, 0xfff, 1014 + 0x324, 0xfff, 0xfff, 0x0ca, 0x306, 0xfff, 0x548, 0xfff, 1015 + 0x46e, 0xfff, 0xfff, 0xfff, 0x4b8, 0x1c2, 0x286, 0xfff, 1016 + 0xfff, 0x087, 0x18a, 0x19f, 0xfff, 0xfff, 0xfff, 0xfff, 1017 + 0x18c, 0xfff, 0x215, 0xfff, 0xfff, 0xfff, 0xfff, 0x283, 1018 + 0xfff, 0xfff, 0xfff, 0x126, 0xfff, 0xfff, 0x370, 0xfff, 1019 + 0x53f, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x31c, 0xfff, 1020 + 0x4d1, 0xfff, 0xfff, 0xfff, 0x021, 0xfff, 0x157, 0xfff, 1021 + 0xfff, 0x028, 0x16e, 0xfff, 0x421, 0xfff, 0x1c6, 0xfff, 1022 + 0xfff, 0x511, 0xfff, 0xfff, 0x39c, 0x46f, 0x1b2, 0xfff, 1023 + 0xfff, 0x316, 0xfff, 0xfff, 0x009, 0xfff, 0xfff, 0x195, 1024 + 0xfff, 0x240, 0x546, 0xfff, 0xfff, 0x520, 0xfff, 0xfff, 1025 + 0xfff, 0xfff, 0xfff, 0xfff, 0x454, 0xfff, 0xfff, 0xfff, 1026 + 0x3f3, 0xfff, 0xfff, 0x187, 0xfff, 0x4a9, 0xfff, 0xfff, 1027 + 0xfff, 0xfff, 0xfff, 0xfff, 0x51c, 0x453, 0x1e6, 0xfff, 1028 + 0xfff, 0xfff, 0x1b0, 0xfff, 0x477, 0xfff, 0xfff, 0xfff, 1029 + 0x4fe, 0xfff, 0x32f, 0xfff, 0xfff, 0x15e, 0x1d4, 0xfff, 1030 + 0x0e5, 0xfff, 0xfff, 0xfff, 0x242, 0x14b, 0x046, 0xfff, 1031 + 0x3f6, 0x3bb, 0x3e4, 0xfff, 0xfff, 0x2e3, 0xfff, 0x245, 1032 + 0xfff, 0x149, 0xfff, 0xfff, 0xfff, 0x2db, 0xfff, 0xfff, 1033 + 0x181, 0xfff, 0x089, 0x2c5, 0xfff, 0x1f5, 0xfff, 0x2d6, 1034 + 0x507, 0xfff, 0x42d, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 1035 + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 1036 + 0x080, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 1037 + 0xfff, 0xfff, 0xfff, 0xfff, 0x3c3, 0x320, 0xfff, 0x1e1, 1038 + 0xfff, 0x0f5, 0x13b, 0xfff, 0xfff, 0xfff, 0x003, 0x4da, 1039 + 0xfff, 0xfff, 0xfff, 0x42c, 0xfff, 0xfff, 0x0cb, 0xfff, 1040 + 0x536, 0x2c3, 0xfff, 0xfff, 0xfff, 0xfff, 0x199, 0xfff, 1041 + 0xfff, 0x0c0, 0xfff, 0x01e, 0x497, 0xfff, 0xfff, 0x3e5, 1042 + 0xfff, 0xfff, 0xfff, 0x0cf, 0xfff, 0x2bd, 0xfff, 0x223, 1043 + 0xfff, 0x3ff, 0xfff, 0x058, 0x174, 0x3ef, 0xfff, 0x002 1044 + }; 1045 + 1046 + static unsigned short err_pos(unsigned short din) 1047 + { 1048 + BUG_ON(din > 4096); 1049 + return err_pos_lut[din]; 1050 + } 1051 + static int chk_no_err_only(unsigned short *chk_syndrome_list, unsigned short *err_info) 1052 + { 1053 + if ((chk_syndrome_list[0] | chk_syndrome_list[1] | 1054 + chk_syndrome_list[2] | chk_syndrome_list[3] | 1055 + chk_syndrome_list[4] | chk_syndrome_list[5] | 1056 + chk_syndrome_list[6] | chk_syndrome_list[7]) != 0x0) { 1057 + return -EINVAL; 1058 + } else { 1059 + err_info[0] = 0x0; 1060 + return 0; 1061 + } 1062 + } 1063 + static int chk_1_err_only(unsigned short *chk_syndrome_list, unsigned short *err_info) 1064 + { 1065 + unsigned short tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6; 1066 + tmp0 = gf4096_mul(chk_syndrome_list[1], gf4096_inv(chk_syndrome_list[0])); 1067 + tmp1 = gf4096_mul(chk_syndrome_list[2], gf4096_inv(chk_syndrome_list[1])); 1068 + tmp2 = gf4096_mul(chk_syndrome_list[3], gf4096_inv(chk_syndrome_list[2])); 1069 + tmp3 = gf4096_mul(chk_syndrome_list[4], gf4096_inv(chk_syndrome_list[3])); 1070 + tmp4 = gf4096_mul(chk_syndrome_list[5], gf4096_inv(chk_syndrome_list[4])); 1071 + tmp5 = gf4096_mul(chk_syndrome_list[6], gf4096_inv(chk_syndrome_list[5])); 1072 + tmp6 = gf4096_mul(chk_syndrome_list[7], gf4096_inv(chk_syndrome_list[6])); 1073 + if ((tmp0 == tmp1) & (tmp1 == tmp2) & (tmp2 == tmp3) & (tmp3 == tmp4) & (tmp4 == tmp5) & (tmp5 == tmp6)) { 1074 + err_info[0] = 0x1; // encode 1-symbol error as 0x1 1075 + err_info[1] = err_pos(tmp0); 1076 + err_info[1] = (unsigned short)(0x55e - err_info[1]); 1077 + err_info[5] = chk_syndrome_list[0]; 1078 + return 0; 1079 + } else 1080 + return -EINVAL; 1081 + } 1082 + static int chk_2_err_only(unsigned short *chk_syndrome_list, unsigned short *err_info) 1083 + { 1084 + unsigned short tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; 1085 + unsigned short coefs[4]; 1086 + unsigned short err_pats[4]; 1087 + int found_num_root = 0; 1088 + unsigned short bit2_root0, bit2_root1; 1089 + unsigned short bit2_root0_inv, bit2_root1_inv; 1090 + unsigned short err_loc_eqn, test_root; 1091 + unsigned short bit2_loc0, bit2_loc1; 1092 + unsigned short bit2_pat0, bit2_pat1; 1093 + 1094 + find_2x2_soln(chk_syndrome_list[1], 1095 + chk_syndrome_list[0], 1096 + chk_syndrome_list[2], chk_syndrome_list[1], chk_syndrome_list[2], chk_syndrome_list[3], coefs); 1097 + for (test_root = 0x1; test_root < 0xfff; test_root++) { 1098 + err_loc_eqn = 1099 + gf4096_mul(coefs[1], gf4096_mul(test_root, test_root)) ^ gf4096_mul(coefs[0], test_root) ^ 0x1; 1100 + if (err_loc_eqn == 0x0) { 1101 + if (found_num_root == 0) { 1102 + bit2_root0 = test_root; 1103 + found_num_root = 1; 1104 + } else if (found_num_root == 1) { 1105 + bit2_root1 = test_root; 1106 + found_num_root = 2; 1107 + break; 1108 + } 1109 + } 1110 + } 1111 + if (found_num_root != 2) 1112 + return -EINVAL; 1113 + else { 1114 + bit2_root0_inv = gf4096_inv(bit2_root0); 1115 + bit2_root1_inv = gf4096_inv(bit2_root1); 1116 + find_2bit_err_pats(chk_syndrome_list[0], 1117 + chk_syndrome_list[1], bit2_root0_inv, bit2_root1_inv, err_pats); 1118 + bit2_pat0 = err_pats[0]; 1119 + bit2_pat1 = err_pats[1]; 1120 + //for(x+1) 1121 + tmp0 = gf4096_mul(gf4096_mul(bit2_root0_inv, bit2_root0_inv), gf4096_mul(bit2_root0_inv, bit2_root0_inv)); //rinv0^4 1122 + tmp1 = gf4096_mul(bit2_root0_inv, tmp0); //rinv0^5 1123 + tmp2 = gf4096_mul(bit2_root0_inv, tmp1); //rinv0^6 1124 + tmp3 = gf4096_mul(bit2_root0_inv, tmp2); //rinv0^7 1125 + tmp4 = gf4096_mul(gf4096_mul(bit2_root1_inv, bit2_root1_inv), gf4096_mul(bit2_root1_inv, bit2_root1_inv)); //rinv1^4 1126 + tmp5 = gf4096_mul(bit2_root1_inv, tmp4); //rinv1^5 1127 + tmp6 = gf4096_mul(bit2_root1_inv, tmp5); //rinv1^6 1128 + tmp7 = gf4096_mul(bit2_root1_inv, tmp6); //rinv1^7 1129 + //check if only 2-bit error 1130 + if ((chk_syndrome_list[4] == 1131 + (gf4096_mul(bit2_pat0, tmp0) ^ 1132 + gf4096_mul(bit2_pat1, 1133 + tmp4))) & (chk_syndrome_list[5] == 1134 + (gf4096_mul(bit2_pat0, tmp1) ^ 1135 + gf4096_mul(bit2_pat1, 1136 + tmp5))) & 1137 + (chk_syndrome_list[6] == 1138 + (gf4096_mul(bit2_pat0, tmp2) ^ 1139 + gf4096_mul(bit2_pat1, 1140 + tmp6))) & (chk_syndrome_list[7] == 1141 + (gf4096_mul(bit2_pat0, tmp3) ^ gf4096_mul(bit2_pat1, tmp7)))) { 1142 + if ((err_pos(bit2_root0_inv) == 0xfff) | (err_pos(bit2_root1_inv) == 0xfff)) { 1143 + return -EINVAL; 1144 + } else { 1145 + bit2_loc0 = 0x55e - err_pos(bit2_root0_inv); 1146 + bit2_loc1 = 0x55e - err_pos(bit2_root1_inv); 1147 + err_info[0] = 0x2; // encode 2-symbol error as 0x2 1148 + err_info[1] = bit2_loc0; 1149 + err_info[2] = bit2_loc1; 1150 + err_info[5] = bit2_pat0; 1151 + err_info[6] = bit2_pat1; 1152 + return 0; 1153 + } 1154 + } else 1155 + return -EINVAL; 1156 + } 1157 + } 1158 + static int chk_3_err_only(unsigned short *chk_syndrome_list, unsigned short *err_info) 1159 + { 1160 + unsigned short tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; 1161 + unsigned short coefs[4]; 1162 + unsigned short err_pats[4]; 1163 + int found_num_root = 0; 1164 + unsigned short bit3_root0, bit3_root1, bit3_root2; 1165 + unsigned short bit3_root0_inv, bit3_root1_inv, bit3_root2_inv; 1166 + unsigned short err_loc_eqn, test_root; 1167 + 1168 + find_3bit_err_coefs(chk_syndrome_list[0], chk_syndrome_list[1], 1169 + chk_syndrome_list[2], chk_syndrome_list[3], 1170 + chk_syndrome_list[4], chk_syndrome_list[5], coefs); 1171 + 1172 + for (test_root = 0x1; test_root < 0xfff; test_root++) { 1173 + err_loc_eqn = gf4096_mul(coefs[2], 1174 + gf4096_mul(gf4096_mul(test_root, test_root), 1175 + test_root)) ^ gf4096_mul(coefs[1], gf4096_mul(test_root, test_root)) 1176 + ^ gf4096_mul(coefs[0], test_root) ^ 0x1; 1177 + 1178 + if (err_loc_eqn == 0x0) { 1179 + if (found_num_root == 0) { 1180 + bit3_root0 = test_root; 1181 + found_num_root = 1; 1182 + } else if (found_num_root == 1) { 1183 + bit3_root1 = test_root; 1184 + found_num_root = 2; 1185 + } else if (found_num_root == 2) { 1186 + bit3_root2 = test_root; 1187 + found_num_root = 3; 1188 + break; 1189 + } 1190 + } 1191 + } 1192 + if (found_num_root != 3) 1193 + return -EINVAL; 1194 + else { 1195 + bit3_root0_inv = gf4096_inv(bit3_root0); 1196 + bit3_root1_inv = gf4096_inv(bit3_root1); 1197 + bit3_root2_inv = gf4096_inv(bit3_root2); 1198 + 1199 + find_3bit_err_pats(chk_syndrome_list[0], chk_syndrome_list[1], 1200 + chk_syndrome_list[2], bit3_root0_inv, 1201 + bit3_root1_inv, bit3_root2_inv, err_pats); 1202 + 1203 + //check if only 3-bit error 1204 + tmp0 = gf4096_mul(bit3_root0_inv, bit3_root0_inv); 1205 + tmp0 = gf4096_mul(tmp0, tmp0); 1206 + tmp0 = gf4096_mul(tmp0, bit3_root0_inv); 1207 + tmp0 = gf4096_mul(tmp0, bit3_root0_inv); //rinv0^6 1208 + tmp1 = gf4096_mul(tmp0, bit3_root0_inv); //rinv0^7 1209 + tmp2 = gf4096_mul(bit3_root1_inv, bit3_root1_inv); 1210 + tmp2 = gf4096_mul(tmp2, tmp2); 1211 + tmp2 = gf4096_mul(tmp2, bit3_root1_inv); 1212 + tmp2 = gf4096_mul(tmp2, bit3_root1_inv); //rinv1^6 1213 + tmp3 = gf4096_mul(tmp2, bit3_root1_inv); //rinv1^7 1214 + tmp4 = gf4096_mul(bit3_root2_inv, bit3_root2_inv); 1215 + tmp4 = gf4096_mul(tmp4, tmp4); 1216 + tmp4 = gf4096_mul(tmp4, bit3_root2_inv); 1217 + tmp4 = gf4096_mul(tmp4, bit3_root2_inv); //rinv2^6 1218 + tmp5 = gf4096_mul(tmp4, bit3_root2_inv); //rinv2^7 1219 + 1220 + //check if only 3 errors 1221 + if ((chk_syndrome_list[6] == (gf4096_mul(err_pats[0], tmp0) ^ 1222 + gf4096_mul(err_pats[1], tmp2) ^ 1223 + gf4096_mul(err_pats[2], tmp4))) & 1224 + (chk_syndrome_list[7] == (gf4096_mul(err_pats[0], tmp1) ^ 1225 + gf4096_mul(err_pats[1], tmp3) ^ gf4096_mul(err_pats[2], tmp5)))) { 1226 + if ((err_pos(bit3_root0_inv) == 0xfff) | 1227 + (err_pos(bit3_root1_inv) == 0xfff) | (err_pos(bit3_root2_inv) == 0xfff)) { 1228 + return -EINVAL; 1229 + } else { 1230 + err_info[0] = 0x3; 1231 + err_info[1] = (0x55e - err_pos(bit3_root0_inv)); 1232 + err_info[2] = (0x55e - err_pos(bit3_root1_inv)); 1233 + err_info[3] = (0x55e - err_pos(bit3_root2_inv)); 1234 + err_info[5] = err_pats[0]; 1235 + err_info[6] = err_pats[1]; 1236 + err_info[7] = err_pats[2]; 1237 + return 0; 1238 + } 1239 + } else 1240 + return -EINVAL; 1241 + } 1242 + } 1243 + static int chk_4_err_only(unsigned short *chk_syndrome_list, unsigned short *err_info) 1244 + { 1245 + unsigned short coefs[4]; 1246 + unsigned short err_pats[4]; 1247 + int found_num_root = 0; 1248 + unsigned short bit4_root0, bit4_root1, bit4_root2, bit4_root3; 1249 + unsigned short bit4_root0_inv, bit4_root1_inv, bit4_root2_inv, bit4_root3_inv; 1250 + unsigned short err_loc_eqn, test_root; 1251 + 1252 + find_4bit_err_coefs(chk_syndrome_list[0], 1253 + chk_syndrome_list[1], 1254 + chk_syndrome_list[2], 1255 + chk_syndrome_list[3], 1256 + chk_syndrome_list[4], 1257 + chk_syndrome_list[5], chk_syndrome_list[6], chk_syndrome_list[7], coefs); 1258 + 1259 + for (test_root = 0x1; test_root < 0xfff; test_root++) { 1260 + err_loc_eqn = 1261 + gf4096_mul(coefs[3], 1262 + gf4096_mul(gf4096_mul 1263 + (gf4096_mul(test_root, test_root), 1264 + test_root), 1265 + test_root)) ^ gf4096_mul(coefs[2], 1266 + gf4096_mul 1267 + (gf4096_mul(test_root, test_root), test_root)) 1268 + ^ gf4096_mul(coefs[1], gf4096_mul(test_root, test_root)) ^ gf4096_mul(coefs[0], test_root) 1269 + ^ 0x1; 1270 + if (err_loc_eqn == 0x0) { 1271 + if (found_num_root == 0) { 1272 + bit4_root0 = test_root; 1273 + found_num_root = 1; 1274 + } else if (found_num_root == 1) { 1275 + bit4_root1 = test_root; 1276 + found_num_root = 2; 1277 + } else if (found_num_root == 2) { 1278 + bit4_root2 = test_root; 1279 + found_num_root = 3; 1280 + } else { 1281 + found_num_root = 4; 1282 + bit4_root3 = test_root; 1283 + break; 1284 + } 1285 + } 1286 + } 1287 + if (found_num_root != 4) { 1288 + return -EINVAL; 1289 + } else { 1290 + bit4_root0_inv = gf4096_inv(bit4_root0); 1291 + bit4_root1_inv = gf4096_inv(bit4_root1); 1292 + bit4_root2_inv = gf4096_inv(bit4_root2); 1293 + bit4_root3_inv = gf4096_inv(bit4_root3); 1294 + find_4bit_err_pats(chk_syndrome_list[0], 1295 + chk_syndrome_list[1], 1296 + chk_syndrome_list[2], 1297 + chk_syndrome_list[3], 1298 + bit4_root0_inv, bit4_root1_inv, bit4_root2_inv, bit4_root3_inv, err_pats); 1299 + err_info[0] = 0x4; 1300 + err_info[1] = (0x55e - err_pos(bit4_root0_inv)); 1301 + err_info[2] = (0x55e - err_pos(bit4_root1_inv)); 1302 + err_info[3] = (0x55e - err_pos(bit4_root2_inv)); 1303 + err_info[4] = (0x55e - err_pos(bit4_root3_inv)); 1304 + err_info[5] = err_pats[0]; 1305 + err_info[6] = err_pats[1]; 1306 + err_info[7] = err_pats[2]; 1307 + err_info[8] = err_pats[3]; 1308 + return 0; 1309 + } 1310 + } 1311 + 1312 + void correct_12bit_symbol(unsigned char *buf, unsigned short sym, 1313 + unsigned short val) 1314 + { 1315 + if (unlikely(sym > 1366)) { 1316 + printk(KERN_ERR "Error: symbol %d out of range; cannot correct\n", sym); 1317 + } else if (sym == 0) { 1318 + buf[0] ^= val; 1319 + } else if (sym & 1) { 1320 + buf[1+(3*(sym-1))/2] ^= (val >> 4); 1321 + buf[2+(3*(sym-1))/2] ^= ((val & 0xf) << 4); 1322 + } else { 1323 + buf[2+(3*(sym-2))/2] ^= (val >> 8); 1324 + buf[3+(3*(sym-2))/2] ^= (val & 0xff); 1325 + } 1326 + } 1327 + 1328 + static int debugecc = 0; 1329 + module_param(debugecc, int, 0644); 1330 + 1331 + int cafe_correct_ecc(unsigned char *buf, 1332 + unsigned short *chk_syndrome_list) 1333 + { 1334 + unsigned short err_info[9]; 1335 + int i; 1336 + 1337 + if (debugecc) { 1338 + printk(KERN_WARNING "cafe_correct_ecc invoked. Syndromes %x %x %x %x %x %x %x %x\n", 1339 + chk_syndrome_list[0], chk_syndrome_list[1], 1340 + chk_syndrome_list[2], chk_syndrome_list[3], 1341 + chk_syndrome_list[4], chk_syndrome_list[5], 1342 + chk_syndrome_list[6], chk_syndrome_list[7]); 1343 + for (i=0; i < 2048; i+=16) { 1344 + printk(KERN_WARNING "D %04x: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", 1345 + i, 1346 + buf[i], buf[i+1], buf[i+2], buf[i+3], 1347 + buf[i+4], buf[i+5], buf[i+6], buf[i+7], 1348 + buf[i+8], buf[i+9], buf[i+10], buf[i+11], 1349 + buf[i+12], buf[i+13], buf[i+14], buf[i+15]); 1350 + } 1351 + for ( ; i < 2112; i+=16) { 1352 + printk(KERN_WARNING "O %02x: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", 1353 + i - 2048, 1354 + buf[i], buf[i+1], buf[i+2], buf[i+3], 1355 + buf[i+4], buf[i+5], buf[i+6], buf[i+7], 1356 + buf[i+8], buf[i+9], buf[i+10], buf[i+11], 1357 + buf[i+12], buf[i+13], buf[i+14], buf[i+15]); 1358 + } 1359 + } 1360 + 1361 + 1362 + 1363 + if (chk_no_err_only(chk_syndrome_list, err_info) && 1364 + chk_1_err_only(chk_syndrome_list, err_info) && 1365 + chk_2_err_only(chk_syndrome_list, err_info) && 1366 + chk_3_err_only(chk_syndrome_list, err_info) && 1367 + chk_4_err_only(chk_syndrome_list, err_info)) { 1368 + return -EIO; 1369 + } 1370 + 1371 + for (i=0; i < err_info[0]; i++) { 1372 + if (debugecc) 1373 + printk(KERN_WARNING "Correct symbol %d with 0x%03x\n", 1374 + err_info[1+i], err_info[5+i]); 1375 + 1376 + correct_12bit_symbol(buf, err_info[1+i], err_info[5+i]); 1377 + } 1378 + 1379 + return err_info[0]; 1380 + } 1381 +
+2 -2
drivers/mtd/nand/cs553x_nand.c
··· 11 * published by the Free Software Foundation. 12 * 13 * Overview: 14 - * This is a device driver for the NAND flash controller found on 15 * the AMD CS5535/CS5536 companion chipsets for the Geode processor. 16 * 17 */ ··· 303 err = cs553x_init_one(i, !!(val & FLSH_MEM_IO), val & 0xFFFFFFFF); 304 } 305 306 - /* Register all devices together here. This means we can easily hack it to 307 do mtdconcat etc. if we want to. */ 308 for (i = 0; i < NR_CS553X_CONTROLLERS; i++) { 309 if (cs553x_mtd[i]) {
··· 11 * published by the Free Software Foundation. 12 * 13 * Overview: 14 + * This is a device driver for the NAND flash controller found on 15 * the AMD CS5535/CS5536 companion chipsets for the Geode processor. 16 * 17 */ ··· 303 err = cs553x_init_one(i, !!(val & FLSH_MEM_IO), val & 0xFFFFFFFF); 304 } 305 306 + /* Register all devices together here. This means we can easily hack it to 307 do mtdconcat etc. if we want to. */ 308 for (i = 0; i < NR_CS553X_CONTROLLERS; i++) { 309 if (cs553x_mtd[i]) {
+1 -2
drivers/mtd/nand/diskonchip.c
··· 1635 1636 len = sizeof(struct mtd_info) + 1637 sizeof(struct nand_chip) + sizeof(struct doc_priv) + (2 * sizeof(struct nand_bbt_descr)); 1638 - mtd = kmalloc(len, GFP_KERNEL); 1639 if (!mtd) { 1640 printk(KERN_ERR "DiskOnChip kmalloc (%d bytes) failed!\n", len); 1641 ret = -ENOMEM; 1642 goto fail; 1643 } 1644 - memset(mtd, 0, len); 1645 1646 nand = (struct nand_chip *) (mtd + 1); 1647 doc = (struct doc_priv *) (nand + 1);
··· 1635 1636 len = sizeof(struct mtd_info) + 1637 sizeof(struct nand_chip) + sizeof(struct doc_priv) + (2 * sizeof(struct nand_bbt_descr)); 1638 + mtd = kzalloc(len, GFP_KERNEL); 1639 if (!mtd) { 1640 printk(KERN_ERR "DiskOnChip kmalloc (%d bytes) failed!\n", len); 1641 ret = -ENOMEM; 1642 goto fail; 1643 } 1644 1645 nand = (struct nand_chip *) (mtd + 1); 1646 doc = (struct doc_priv *) (nand + 1);
+91 -42
drivers/mtd/nand/nand_base.c
··· 362 * access 363 */ 364 ofs += mtd->oobsize; 365 - chip->ops.len = 2; 366 chip->ops.datbuf = NULL; 367 chip->ops.oobbuf = buf; 368 chip->ops.ooboffs = chip->badblockpos & ~0x01; ··· 755 } 756 757 /** 758 - * nand_read_page_swecc - {REPLACABLE] software ecc based page read function 759 * @mtd: mtd info structure 760 * @chip: nand chip info structure 761 * @buf: buffer to store read data ··· 795 } 796 797 /** 798 - * nand_read_page_hwecc - {REPLACABLE] hardware ecc based page read function 799 * @mtd: mtd info structure 800 * @chip: nand chip info structure 801 * @buf: buffer to store read data ··· 839 } 840 841 /** 842 - * nand_read_page_syndrome - {REPLACABLE] hardware ecc syndrom based page read 843 * @mtd: mtd info structure 844 * @chip: nand chip info structure 845 * @buf: buffer to store read data ··· 897 * @chip: nand chip structure 898 * @oob: oob destination address 899 * @ops: oob ops structure 900 */ 901 static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob, 902 - struct mtd_oob_ops *ops) 903 { 904 - size_t len = ops->ooblen; 905 - 906 switch(ops->mode) { 907 908 case MTD_OOB_PLACE: ··· 959 int sndcmd = 1; 960 int ret = 0; 961 uint32_t readlen = ops->len; 962 uint8_t *bufpoi, *oob, *buf; 963 964 stats = mtd->ecc_stats; ··· 971 page = realpage & chip->pagemask; 972 973 col = (int)(from & (mtd->writesize - 1)); 974 - chip->oob_poi = chip->buffers->oobrbuf; 975 976 buf = ops->datbuf; 977 oob = ops->oobbuf; ··· 1006 1007 if (unlikely(oob)) { 1008 /* Raw mode does data:oob:data:oob */ 1009 - if (ops->mode != MTD_OOB_RAW) 1010 - oob = nand_transfer_oob(chip, oob, ops); 1011 - else 1012 - buf = nand_transfer_oob(chip, buf, ops); 1013 } 1014 1015 if (!(chip->options & NAND_NO_READRDY)) { ··· 1063 } 1064 1065 ops->retlen = ops->len - (size_t) readlen; 1066 1067 if (ret) 1068 return ret; ··· 1265 int page, realpage, chipnr, sndcmd = 1; 1266 struct nand_chip *chip = mtd->priv; 1267 int blkcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1; 1268 - int readlen = ops->len; 1269 uint8_t *buf = ops->oobbuf; 1270 1271 DEBUG(MTD_DEBUG_LEVEL3, "nand_read_oob: from = 0x%08Lx, len = %i\n", 1272 (unsigned long long)from, readlen); 1273 1274 chipnr = (int)(from >> chip->chip_shift); 1275 chip->select_chip(mtd, chipnr); ··· 1284 realpage = (int)(from >> chip->page_shift); 1285 page = realpage & chip->pagemask; 1286 1287 - chip->oob_poi = chip->buffers->oobrbuf; 1288 - 1289 while(1) { 1290 sndcmd = chip->ecc.read_oob(mtd, chip, page, sndcmd); 1291 - buf = nand_transfer_oob(chip, buf, ops); 1292 1293 if (!(chip->options & NAND_NO_READRDY)) { 1294 /* ··· 1303 nand_wait_ready(mtd); 1304 } 1305 1306 - readlen -= ops->ooblen; 1307 if (!readlen) 1308 break; 1309 ··· 1325 sndcmd = 1; 1326 } 1327 1328 - ops->retlen = ops->len; 1329 return 0; 1330 } 1331 ··· 1346 ops->retlen = 0; 1347 1348 /* Do not allow reads past end of device */ 1349 - if ((from + ops->len) > mtd->size) { 1350 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: " 1351 "Attempt read beyond end of device\n"); 1352 return -EINVAL; ··· 1389 } 1390 1391 /** 1392 - * nand_write_page_swecc - {REPLACABLE] software ecc based page write function 1393 * @mtd: mtd info structure 1394 * @chip: nand chip info structure 1395 * @buf: data buffer ··· 1415 } 1416 1417 /** 1418 - * nand_write_page_hwecc - {REPLACABLE] hardware ecc based page write function 1419 * @mtd: mtd info structure 1420 * @chip: nand chip info structure 1421 * @buf: data buffer ··· 1443 } 1444 1445 /** 1446 - * nand_write_page_syndrome - {REPLACABLE] hardware ecc syndrom based page write 1447 * @mtd: mtd info structure 1448 * @chip: nand chip info structure 1449 * @buf: data buffer ··· 1591 return NULL; 1592 } 1593 1594 - #define NOTALIGNED(x) (x & (mtd->writesize-1)) != 0 1595 1596 /** 1597 * nand_do_write_ops - [Internal] NAND write with ECC ··· 1604 static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, 1605 struct mtd_oob_ops *ops) 1606 { 1607 - int chipnr, realpage, page, blockmask; 1608 struct nand_chip *chip = mtd->priv; 1609 uint32_t writelen = ops->len; 1610 uint8_t *oob = ops->oobbuf; 1611 uint8_t *buf = ops->datbuf; 1612 - int bytes = mtd->writesize; 1613 - int ret; 1614 1615 ops->retlen = 0; 1616 1617 /* reject writes, which are not page aligned */ 1618 if (NOTALIGNED(to) || NOTALIGNED(ops->len)) { ··· 1622 return -EINVAL; 1623 } 1624 1625 - if (!writelen) 1626 - return 0; 1627 1628 chipnr = (int)(to >> chip->chip_shift); 1629 chip->select_chip(mtd, chipnr); ··· 1644 (chip->pagebuf << chip->page_shift) < (to + ops->len)) 1645 chip->pagebuf = -1; 1646 1647 - chip->oob_poi = chip->buffers->oobwbuf; 1648 1649 while(1) { 1650 int cached = writelen > bytes && page != blockmask; 1651 1652 if (unlikely(oob)) 1653 oob = nand_fill_oob(chip, oob, ops); 1654 1655 - ret = chip->write_page(mtd, chip, buf, page, cached, 1656 (ops->mode == MTD_OOB_RAW)); 1657 if (ret) 1658 break; ··· 1675 if (!writelen) 1676 break; 1677 1678 buf += bytes; 1679 realpage++; 1680 ··· 1688 } 1689 } 1690 1691 - if (unlikely(oob)) 1692 - memset(chip->oob_poi, 0xff, mtd->oobsize); 1693 - 1694 ops->retlen = ops->len - writelen; 1695 return ret; 1696 } 1697 ··· 1746 struct nand_chip *chip = mtd->priv; 1747 1748 DEBUG(MTD_DEBUG_LEVEL3, "nand_write_oob: to = 0x%08x, len = %i\n", 1749 - (unsigned int)to, (int)ops->len); 1750 1751 /* Do not allow write past end of page */ 1752 - if ((ops->ooboffs + ops->len) > mtd->oobsize) { 1753 DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: " 1754 "Attempt to write past end of page\n"); 1755 return -EINVAL; ··· 1777 if (page == chip->pagebuf) 1778 chip->pagebuf = -1; 1779 1780 - chip->oob_poi = chip->buffers->oobwbuf; 1781 memset(chip->oob_poi, 0xff, mtd->oobsize); 1782 nand_fill_oob(chip, ops->oobbuf, ops); 1783 status = chip->ecc.write_oob(mtd, chip, page & chip->pagemask); ··· 1785 if (status) 1786 return status; 1787 1788 - ops->retlen = ops->len; 1789 1790 return 0; 1791 } ··· 1805 ops->retlen = 0; 1806 1807 /* Do not allow writes past end of device */ 1808 - if ((to + ops->len) > mtd->size) { 1809 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: " 1810 "Attempt read beyond end of device\n"); 1811 return -EINVAL; ··· 2219 /* Newer devices have all the information in additional id bytes */ 2220 if (!type->pagesize) { 2221 int extid; 2222 - /* The 3rd id byte contains non relevant data ATM */ 2223 - extid = chip->read_byte(mtd); 2224 /* The 4th id byte is the important one */ 2225 extid = chip->read_byte(mtd); 2226 /* Calc pagesize */ ··· 2380 if (!chip->buffers) 2381 return -ENOMEM; 2382 2383 - /* Preset the internal oob write buffer */ 2384 - memset(chip->buffers->oobwbuf, 0xff, mtd->oobsize); 2385 2386 /* 2387 * If no default placement scheme is given, select an appropriate one ··· 2499 BUG(); 2500 } 2501 chip->ecc.total = chip->ecc.steps * chip->ecc.bytes; 2502 2503 /* Initialize state */ 2504 chip->state = FL_READY;
··· 362 * access 363 */ 364 ofs += mtd->oobsize; 365 + chip->ops.len = chip->ops.ooblen = 2; 366 chip->ops.datbuf = NULL; 367 chip->ops.oobbuf = buf; 368 chip->ops.ooboffs = chip->badblockpos & ~0x01; ··· 755 } 756 757 /** 758 + * nand_read_page_swecc - [REPLACABLE] software ecc based page read function 759 * @mtd: mtd info structure 760 * @chip: nand chip info structure 761 * @buf: buffer to store read data ··· 795 } 796 797 /** 798 + * nand_read_page_hwecc - [REPLACABLE] hardware ecc based page read function 799 * @mtd: mtd info structure 800 * @chip: nand chip info structure 801 * @buf: buffer to store read data ··· 839 } 840 841 /** 842 + * nand_read_page_syndrome - [REPLACABLE] hardware ecc syndrom based page read 843 * @mtd: mtd info structure 844 * @chip: nand chip info structure 845 * @buf: buffer to store read data ··· 897 * @chip: nand chip structure 898 * @oob: oob destination address 899 * @ops: oob ops structure 900 + * @len: size of oob to transfer 901 */ 902 static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob, 903 + struct mtd_oob_ops *ops, size_t len) 904 { 905 switch(ops->mode) { 906 907 case MTD_OOB_PLACE: ··· 960 int sndcmd = 1; 961 int ret = 0; 962 uint32_t readlen = ops->len; 963 + uint32_t oobreadlen = ops->ooblen; 964 uint8_t *bufpoi, *oob, *buf; 965 966 stats = mtd->ecc_stats; ··· 971 page = realpage & chip->pagemask; 972 973 col = (int)(from & (mtd->writesize - 1)); 974 975 buf = ops->datbuf; 976 oob = ops->oobbuf; ··· 1007 1008 if (unlikely(oob)) { 1009 /* Raw mode does data:oob:data:oob */ 1010 + if (ops->mode != MTD_OOB_RAW) { 1011 + int toread = min(oobreadlen, 1012 + chip->ecc.layout->oobavail); 1013 + if (toread) { 1014 + oob = nand_transfer_oob(chip, 1015 + oob, ops, toread); 1016 + oobreadlen -= toread; 1017 + } 1018 + } else 1019 + buf = nand_transfer_oob(chip, 1020 + buf, ops, mtd->oobsize); 1021 } 1022 1023 if (!(chip->options & NAND_NO_READRDY)) { ··· 1057 } 1058 1059 ops->retlen = ops->len - (size_t) readlen; 1060 + if (oob) 1061 + ops->oobretlen = ops->ooblen - oobreadlen; 1062 1063 if (ret) 1064 return ret; ··· 1257 int page, realpage, chipnr, sndcmd = 1; 1258 struct nand_chip *chip = mtd->priv; 1259 int blkcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1; 1260 + int readlen = ops->ooblen; 1261 + int len; 1262 uint8_t *buf = ops->oobbuf; 1263 1264 DEBUG(MTD_DEBUG_LEVEL3, "nand_read_oob: from = 0x%08Lx, len = %i\n", 1265 (unsigned long long)from, readlen); 1266 + 1267 + if (ops->mode == MTD_OOB_RAW) 1268 + len = mtd->oobsize; 1269 + else 1270 + len = chip->ecc.layout->oobavail; 1271 1272 chipnr = (int)(from >> chip->chip_shift); 1273 chip->select_chip(mtd, chipnr); ··· 1270 realpage = (int)(from >> chip->page_shift); 1271 page = realpage & chip->pagemask; 1272 1273 while(1) { 1274 sndcmd = chip->ecc.read_oob(mtd, chip, page, sndcmd); 1275 + 1276 + len = min(len, readlen); 1277 + buf = nand_transfer_oob(chip, buf, ops, len); 1278 1279 if (!(chip->options & NAND_NO_READRDY)) { 1280 /* ··· 1289 nand_wait_ready(mtd); 1290 } 1291 1292 + readlen -= len; 1293 if (!readlen) 1294 break; 1295 ··· 1311 sndcmd = 1; 1312 } 1313 1314 + ops->oobretlen = ops->ooblen; 1315 return 0; 1316 } 1317 ··· 1332 ops->retlen = 0; 1333 1334 /* Do not allow reads past end of device */ 1335 + if (ops->datbuf && (from + ops->len) > mtd->size) { 1336 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: " 1337 "Attempt read beyond end of device\n"); 1338 return -EINVAL; ··· 1375 } 1376 1377 /** 1378 + * nand_write_page_swecc - [REPLACABLE] software ecc based page write function 1379 * @mtd: mtd info structure 1380 * @chip: nand chip info structure 1381 * @buf: data buffer ··· 1401 } 1402 1403 /** 1404 + * nand_write_page_hwecc - [REPLACABLE] hardware ecc based page write function 1405 * @mtd: mtd info structure 1406 * @chip: nand chip info structure 1407 * @buf: data buffer ··· 1429 } 1430 1431 /** 1432 + * nand_write_page_syndrome - [REPLACABLE] hardware ecc syndrom based page write 1433 * @mtd: mtd info structure 1434 * @chip: nand chip info structure 1435 * @buf: data buffer ··· 1577 return NULL; 1578 } 1579 1580 + #define NOTALIGNED(x) (x & (chip->subpagesize - 1)) != 0 1581 1582 /** 1583 * nand_do_write_ops - [Internal] NAND write with ECC ··· 1590 static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, 1591 struct mtd_oob_ops *ops) 1592 { 1593 + int chipnr, realpage, page, blockmask, column; 1594 struct nand_chip *chip = mtd->priv; 1595 uint32_t writelen = ops->len; 1596 uint8_t *oob = ops->oobbuf; 1597 uint8_t *buf = ops->datbuf; 1598 + int ret, subpage; 1599 1600 ops->retlen = 0; 1601 + if (!writelen) 1602 + return 0; 1603 1604 /* reject writes, which are not page aligned */ 1605 if (NOTALIGNED(to) || NOTALIGNED(ops->len)) { ··· 1607 return -EINVAL; 1608 } 1609 1610 + column = to & (mtd->writesize - 1); 1611 + subpage = column || (writelen & (mtd->writesize - 1)); 1612 + 1613 + if (subpage && oob) 1614 + return -EINVAL; 1615 1616 chipnr = (int)(to >> chip->chip_shift); 1617 chip->select_chip(mtd, chipnr); ··· 1626 (chip->pagebuf << chip->page_shift) < (to + ops->len)) 1627 chip->pagebuf = -1; 1628 1629 + /* If we're not given explicit OOB data, let it be 0xFF */ 1630 + if (likely(!oob)) 1631 + memset(chip->oob_poi, 0xff, mtd->oobsize); 1632 1633 while(1) { 1634 + int bytes = mtd->writesize; 1635 int cached = writelen > bytes && page != blockmask; 1636 + uint8_t *wbuf = buf; 1637 + 1638 + /* Partial page write ? */ 1639 + if (unlikely(column || writelen < (mtd->writesize - 1))) { 1640 + cached = 0; 1641 + bytes = min_t(int, bytes - column, (int) writelen); 1642 + chip->pagebuf = -1; 1643 + memset(chip->buffers->databuf, 0xff, mtd->writesize); 1644 + memcpy(&chip->buffers->databuf[column], buf, bytes); 1645 + wbuf = chip->buffers->databuf; 1646 + } 1647 1648 if (unlikely(oob)) 1649 oob = nand_fill_oob(chip, oob, ops); 1650 1651 + ret = chip->write_page(mtd, chip, wbuf, page, cached, 1652 (ops->mode == MTD_OOB_RAW)); 1653 if (ret) 1654 break; ··· 1643 if (!writelen) 1644 break; 1645 1646 + column = 0; 1647 buf += bytes; 1648 realpage++; 1649 ··· 1655 } 1656 } 1657 1658 ops->retlen = ops->len - writelen; 1659 + if (unlikely(oob)) 1660 + ops->oobretlen = ops->ooblen; 1661 return ret; 1662 } 1663 ··· 1714 struct nand_chip *chip = mtd->priv; 1715 1716 DEBUG(MTD_DEBUG_LEVEL3, "nand_write_oob: to = 0x%08x, len = %i\n", 1717 + (unsigned int)to, (int)ops->ooblen); 1718 1719 /* Do not allow write past end of page */ 1720 + if ((ops->ooboffs + ops->ooblen) > mtd->oobsize) { 1721 DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: " 1722 "Attempt to write past end of page\n"); 1723 return -EINVAL; ··· 1745 if (page == chip->pagebuf) 1746 chip->pagebuf = -1; 1747 1748 memset(chip->oob_poi, 0xff, mtd->oobsize); 1749 nand_fill_oob(chip, ops->oobbuf, ops); 1750 status = chip->ecc.write_oob(mtd, chip, page & chip->pagemask); ··· 1754 if (status) 1755 return status; 1756 1757 + ops->oobretlen = ops->ooblen; 1758 1759 return 0; 1760 } ··· 1774 ops->retlen = 0; 1775 1776 /* Do not allow writes past end of device */ 1777 + if (ops->datbuf && (to + ops->len) > mtd->size) { 1778 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: " 1779 "Attempt read beyond end of device\n"); 1780 return -EINVAL; ··· 2188 /* Newer devices have all the information in additional id bytes */ 2189 if (!type->pagesize) { 2190 int extid; 2191 + /* The 3rd id byte holds MLC / multichip data */ 2192 + chip->cellinfo = chip->read_byte(mtd); 2193 /* The 4th id byte is the important one */ 2194 extid = chip->read_byte(mtd); 2195 /* Calc pagesize */ ··· 2349 if (!chip->buffers) 2350 return -ENOMEM; 2351 2352 + /* Set the internal oob buffer location, just after the page data */ 2353 + chip->oob_poi = chip->buffers->databuf + mtd->writesize; 2354 2355 /* 2356 * If no default placement scheme is given, select an appropriate one ··· 2468 BUG(); 2469 } 2470 chip->ecc.total = chip->ecc.steps * chip->ecc.bytes; 2471 + 2472 + /* 2473 + * Allow subpage writes up to ecc.steps. Not possible for MLC 2474 + * FLASH. 2475 + */ 2476 + if (!(chip->options & NAND_NO_SUBPAGE_WRITE) && 2477 + !(chip->cellinfo & NAND_CI_CELLTYPE_MSK)) { 2478 + switch(chip->ecc.steps) { 2479 + case 2: 2480 + mtd->subpage_sft = 1; 2481 + break; 2482 + case 4: 2483 + case 8: 2484 + mtd->subpage_sft = 2; 2485 + break; 2486 + } 2487 + } 2488 + chip->subpagesize = mtd->writesize >> mtd->subpage_sft; 2489 2490 /* Initialize state */ 2491 chip->state = FL_READY;
+4 -7
drivers/mtd/nand/nand_bbt.c
··· 333 struct mtd_oob_ops ops; 334 int j, ret; 335 336 - ops.len = mtd->oobsize; 337 ops.ooblen = mtd->oobsize; 338 ops.oobbuf = buf; 339 ops.ooboffs = 0; ··· 675 "bad block table\n"); 676 } 677 /* Read oob data */ 678 - ops.len = (len >> this->page_shift) * mtd->oobsize; 679 ops.oobbuf = &buf[len]; 680 res = mtd->read_oob(mtd, to + mtd->writesize, &ops); 681 - if (res < 0 || ops.retlen != ops.len) 682 goto outerr; 683 684 /* Calc the byte offset in the buffer */ ··· 960 struct nand_bbt_descr *md = this->bbt_md; 961 962 len = mtd->size >> (this->bbt_erase_shift + 2); 963 - /* Allocate memory (2bit per block) */ 964 - this->bbt = kmalloc(len, GFP_KERNEL); 965 if (!this->bbt) { 966 printk(KERN_ERR "nand_scan_bbt: Out of memory\n"); 967 return -ENOMEM; 968 } 969 - /* Clear the memory bad block table */ 970 - memset(this->bbt, 0x00, len); 971 972 /* If no primary table decriptor is given, scan the device 973 * to build a memory based bad block table
··· 333 struct mtd_oob_ops ops; 334 int j, ret; 335 336 ops.ooblen = mtd->oobsize; 337 ops.oobbuf = buf; 338 ops.ooboffs = 0; ··· 676 "bad block table\n"); 677 } 678 /* Read oob data */ 679 + ops.ooblen = (len >> this->page_shift) * mtd->oobsize; 680 ops.oobbuf = &buf[len]; 681 res = mtd->read_oob(mtd, to + mtd->writesize, &ops); 682 + if (res < 0 || ops.oobretlen != ops.ooblen) 683 goto outerr; 684 685 /* Calc the byte offset in the buffer */ ··· 961 struct nand_bbt_descr *md = this->bbt_md; 962 963 len = mtd->size >> (this->bbt_erase_shift + 2); 964 + /* Allocate memory (2bit per block) and clear the memory bad block table */ 965 + this->bbt = kzalloc(len, GFP_KERNEL); 966 if (!this->bbt) { 967 printk(KERN_ERR "nand_scan_bbt: Out of memory\n"); 968 return -ENOMEM; 969 } 970 971 /* If no primary table decriptor is given, scan the device 972 * to build a memory based bad block table
+2 -2
drivers/mtd/nand/nand_ecc.c
··· 112 tmp2 |= (reg2 & 0x01) << 0; /* B7 -> B0 */ 113 114 /* Calculate final ECC code */ 115 - #ifdef CONFIG_NAND_ECC_SMC 116 ecc_code[0] = ~tmp2; 117 ecc_code[1] = ~tmp1; 118 #else ··· 148 { 149 uint8_t s0, s1, s2; 150 151 - #ifdef CONFIG_NAND_ECC_SMC 152 s0 = calc_ecc[0] ^ read_ecc[0]; 153 s1 = calc_ecc[1] ^ read_ecc[1]; 154 s2 = calc_ecc[2] ^ read_ecc[2];
··· 112 tmp2 |= (reg2 & 0x01) << 0; /* B7 -> B0 */ 113 114 /* Calculate final ECC code */ 115 + #ifdef CONFIG_MTD_NAND_ECC_SMC 116 ecc_code[0] = ~tmp2; 117 ecc_code[1] = ~tmp1; 118 #else ··· 148 { 149 uint8_t s0, s1, s2; 150 151 + #ifdef CONFIG_MTD_NAND_ECC_SMC 152 s0 = calc_ecc[0] ^ read_ecc[0]; 153 s1 = calc_ecc[1] ^ read_ecc[1]; 154 s2 = calc_ecc[2] ^ read_ecc[2];
+158 -85
drivers/mtd/nand/nandsim.c
··· 37 #include <linux/mtd/nand.h> 38 #include <linux/mtd/partitions.h> 39 #include <linux/delay.h> 40 - #ifdef CONFIG_NS_ABS_POS 41 - #include <asm/io.h> 42 - #endif 43 - 44 45 /* Default simulator parameters values */ 46 #if !defined(CONFIG_NANDSIM_FIRST_ID_BYTE) || \ ··· 160 /* After a command is input, the simulator goes to one of the following states */ 161 #define STATE_CMD_READ0 0x00000001 /* read data from the beginning of page */ 162 #define STATE_CMD_READ1 0x00000002 /* read data from the second half of page */ 163 - #define STATE_CMD_READSTART 0x00000003 /* read data second command (large page devices) */ 164 #define STATE_CMD_PAGEPROG 0x00000004 /* start page programm */ 165 #define STATE_CMD_READOOB 0x00000005 /* read OOB area */ 166 #define STATE_CMD_ERASE1 0x00000006 /* sector erase first command */ ··· 227 #define NS_MAX_PREVSTATES 1 228 229 /* 230 * The structure which describes all the internal simulator data. 231 */ 232 struct nandsim { ··· 251 uint16_t npstates; /* number of previous states saved */ 252 uint16_t stateidx; /* current state index */ 253 254 - /* The simulated NAND flash image */ 255 - union flash_media { 256 - u_char *byte; 257 - uint16_t *word; 258 - } mem; 259 260 /* Internal buffer of page + OOB size bytes */ 261 - union internal_buffer { 262 - u_char *byte; /* for byte access */ 263 - uint16_t *word; /* for 16-bit word access */ 264 - } buf; 265 266 /* NAND flash "geometry" */ 267 struct nandsin_geometry { ··· 344 static u_char ns_verify_buf[NS_LARGEST_PAGE_SIZE]; 345 346 /* 347 * Initialize the nandsim structure. 348 * 349 * RETURNS: 0 if success, -ERRNO if failure. 350 */ 351 - static int 352 - init_nandsim(struct mtd_info *mtd) 353 { 354 struct nand_chip *chip = (struct nand_chip *)mtd->priv; 355 struct nandsim *ns = (struct nandsim *)(chip->priv); ··· 440 } 441 } else { 442 if (ns->geom.totsz <= (128 << 20)) { 443 - ns->geom.pgaddrbytes = 5; 444 ns->geom.secaddrbytes = 2; 445 } else { 446 ns->geom.pgaddrbytes = 5; ··· 474 printk("sector address bytes: %u\n", ns->geom.secaddrbytes); 475 printk("options: %#x\n", ns->options); 476 477 - /* Map / allocate and initialize the flash image */ 478 - #ifdef CONFIG_NS_ABS_POS 479 - ns->mem.byte = ioremap(CONFIG_NS_ABS_POS, ns->geom.totszoob); 480 - if (!ns->mem.byte) { 481 - NS_ERR("init_nandsim: failed to map the NAND flash image at address %p\n", 482 - (void *)CONFIG_NS_ABS_POS); 483 - return -ENOMEM; 484 - } 485 - #else 486 - ns->mem.byte = vmalloc(ns->geom.totszoob); 487 - if (!ns->mem.byte) { 488 - NS_ERR("init_nandsim: unable to allocate %u bytes for flash image\n", 489 - ns->geom.totszoob); 490 - return -ENOMEM; 491 - } 492 - memset(ns->mem.byte, 0xFF, ns->geom.totszoob); 493 - #endif 494 495 /* Allocate / initialize the internal buffer */ 496 ns->buf.byte = kmalloc(ns->geom.pgszoob, GFP_KERNEL); ··· 494 return 0; 495 496 error: 497 - #ifdef CONFIG_NS_ABS_POS 498 - iounmap(ns->mem.byte); 499 - #else 500 - vfree(ns->mem.byte); 501 - #endif 502 503 return -ENOMEM; 504 } ··· 502 /* 503 * Free the nandsim structure. 504 */ 505 - static void 506 - free_nandsim(struct nandsim *ns) 507 { 508 kfree(ns->buf.byte); 509 - 510 - #ifdef CONFIG_NS_ABS_POS 511 - iounmap(ns->mem.byte); 512 - #else 513 - vfree(ns->mem.byte); 514 - #endif 515 516 return; 517 } ··· 513 /* 514 * Returns the string representation of 'state' state. 515 */ 516 - static char * 517 - get_state_name(uint32_t state) 518 { 519 switch (NS_STATE(state)) { 520 case STATE_CMD_READ0: ··· 571 * 572 * RETURNS: 1 if wrong command, 0 if right. 573 */ 574 - static int 575 - check_command(int cmd) 576 { 577 switch (cmd) { 578 ··· 597 /* 598 * Returns state after command is accepted by command number. 599 */ 600 - static uint32_t 601 - get_state_by_command(unsigned command) 602 { 603 switch (command) { 604 case NAND_CMD_READ0: ··· 633 /* 634 * Move an address byte to the correspondent internal register. 635 */ 636 - static inline void 637 - accept_addr_byte(struct nandsim *ns, u_char bt) 638 { 639 uint byte = (uint)bt; 640 ··· 651 /* 652 * Switch to STATE_READY state. 653 */ 654 - static inline void 655 - switch_to_ready_state(struct nandsim *ns, u_char status) 656 { 657 NS_DBG("switch_to_ready_state: switch to %s state\n", get_state_name(STATE_READY)); 658 ··· 710 * -1 - several matches. 711 * 0 - operation is found. 712 */ 713 - static int 714 - find_operation(struct nandsim *ns, uint32_t flag) 715 { 716 int opsfound = 0; 717 int i, j, idx = 0; ··· 795 } 796 797 /* 798 * If state has any action bit, perform this action. 799 * 800 * RETURNS: 0 if success, -1 if error. 801 */ 802 - static int 803 - do_state_action(struct nandsim *ns, uint32_t action) 804 { 805 - int i, num; 806 int busdiv = ns->busw == 8 ? 1 : 2; 807 808 action &= ACTION_MASK; ··· 905 break; 906 } 907 num = ns->geom.pgszoob - ns->regs.off - ns->regs.column; 908 - memcpy(ns->buf.byte, ns->mem.byte + NS_RAW_OFFSET(ns) + ns->regs.off, num); 909 910 NS_DBG("do_state_action: (ACTION_CPY:) copy %d bytes to int buf, raw offset %d\n", 911 num, NS_RAW_OFFSET(ns) + ns->regs.off); ··· 946 ns->regs.row, NS_RAW_OFFSET(ns)); 947 NS_LOG("erase sector %d\n", ns->regs.row >> (ns->geom.secshift - ns->geom.pgshift)); 948 949 - memset(ns->mem.byte + NS_RAW_OFFSET(ns), 0xFF, ns->geom.secszoob); 950 951 NS_MDELAY(erase_delay); 952 ··· 969 return -1; 970 } 971 972 - for (i = 0; i < num; i++) 973 - ns->mem.byte[NS_RAW_OFFSET(ns) + ns->regs.off + i] &= ns->buf.byte[i]; 974 975 NS_DBG("do_state_action: copy %d bytes from int buf to (%#x, %#x), raw off = %d\n", 976 num, ns->regs.row, ns->regs.column, NS_RAW_OFFSET(ns) + ns->regs.off); ··· 1011 /* 1012 * Switch simulator's state. 1013 */ 1014 - static void 1015 - switch_state(struct nandsim *ns) 1016 { 1017 if (ns->op) { 1018 /* ··· 1152 } 1153 } 1154 1155 - static u_char 1156 - ns_nand_read_byte(struct mtd_info *mtd) 1157 { 1158 struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv; 1159 u_char outb = 0x00; ··· 1225 return outb; 1226 } 1227 1228 - static void 1229 - ns_nand_write_byte(struct mtd_info *mtd, u_char byte) 1230 { 1231 struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv; 1232 ··· 1388 ns_nand_write_byte(mtd, cmd); 1389 } 1390 1391 - static int 1392 - ns_device_ready(struct mtd_info *mtd) 1393 { 1394 NS_DBG("device_ready\n"); 1395 return 1; 1396 } 1397 1398 - static uint16_t 1399 - ns_nand_read_word(struct mtd_info *mtd) 1400 { 1401 struct nand_chip *chip = (struct nand_chip *)mtd->priv; 1402 ··· 1403 return chip->read_byte(mtd) | (chip->read_byte(mtd) << 8); 1404 } 1405 1406 - static void 1407 - ns_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) 1408 { 1409 struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv; 1410 ··· 1430 } 1431 } 1432 1433 - static void 1434 - ns_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) 1435 { 1436 struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv; 1437 ··· 1483 return; 1484 } 1485 1486 - static int 1487 - ns_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len) 1488 { 1489 ns_nand_read_buf(mtd, (u_char *)&ns_verify_buf[0], len); 1490 ··· 1511 } 1512 1513 /* Allocate and initialize mtd_info, nand_chip and nandsim structures */ 1514 - nsmtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip) 1515 + sizeof(struct nandsim), GFP_KERNEL); 1516 if (!nsmtd) { 1517 NS_ERR("unable to allocate core structures.\n"); 1518 return -ENOMEM; 1519 } 1520 - memset(nsmtd, 0, sizeof(struct mtd_info) + sizeof(struct nand_chip) + 1521 - sizeof(struct nandsim)); 1522 chip = (struct nand_chip *)(nsmtd + 1); 1523 nsmtd->priv = (void *)chip; 1524 nand = (struct nandsim *)(chip + 1);
··· 37 #include <linux/mtd/nand.h> 38 #include <linux/mtd/partitions.h> 39 #include <linux/delay.h> 40 41 /* Default simulator parameters values */ 42 #if !defined(CONFIG_NANDSIM_FIRST_ID_BYTE) || \ ··· 164 /* After a command is input, the simulator goes to one of the following states */ 165 #define STATE_CMD_READ0 0x00000001 /* read data from the beginning of page */ 166 #define STATE_CMD_READ1 0x00000002 /* read data from the second half of page */ 167 + #define STATE_CMD_READSTART 0x00000003 /* read data second command (large page devices) */ 168 #define STATE_CMD_PAGEPROG 0x00000004 /* start page programm */ 169 #define STATE_CMD_READOOB 0x00000005 /* read OOB area */ 170 #define STATE_CMD_ERASE1 0x00000006 /* sector erase first command */ ··· 231 #define NS_MAX_PREVSTATES 1 232 233 /* 234 + * A union to represent flash memory contents and flash buffer. 235 + */ 236 + union ns_mem { 237 + u_char *byte; /* for byte access */ 238 + uint16_t *word; /* for 16-bit word access */ 239 + }; 240 + 241 + /* 242 * The structure which describes all the internal simulator data. 243 */ 244 struct nandsim { ··· 247 uint16_t npstates; /* number of previous states saved */ 248 uint16_t stateidx; /* current state index */ 249 250 + /* The simulated NAND flash pages array */ 251 + union ns_mem *pages; 252 253 /* Internal buffer of page + OOB size bytes */ 254 + union ns_mem buf; 255 256 /* NAND flash "geometry" */ 257 struct nandsin_geometry { ··· 346 static u_char ns_verify_buf[NS_LARGEST_PAGE_SIZE]; 347 348 /* 349 + * Allocate array of page pointers and initialize the array to NULL 350 + * pointers. 351 + * 352 + * RETURNS: 0 if success, -ENOMEM if memory alloc fails. 353 + */ 354 + static int alloc_device(struct nandsim *ns) 355 + { 356 + int i; 357 + 358 + ns->pages = vmalloc(ns->geom.pgnum * sizeof(union ns_mem)); 359 + if (!ns->pages) { 360 + NS_ERR("alloc_map: unable to allocate page array\n"); 361 + return -ENOMEM; 362 + } 363 + for (i = 0; i < ns->geom.pgnum; i++) { 364 + ns->pages[i].byte = NULL; 365 + } 366 + 367 + return 0; 368 + } 369 + 370 + /* 371 + * Free any allocated pages, and free the array of page pointers. 372 + */ 373 + static void free_device(struct nandsim *ns) 374 + { 375 + int i; 376 + 377 + if (ns->pages) { 378 + for (i = 0; i < ns->geom.pgnum; i++) { 379 + if (ns->pages[i].byte) 380 + kfree(ns->pages[i].byte); 381 + } 382 + vfree(ns->pages); 383 + } 384 + } 385 + 386 + /* 387 * Initialize the nandsim structure. 388 * 389 * RETURNS: 0 if success, -ERRNO if failure. 390 */ 391 + static int init_nandsim(struct mtd_info *mtd) 392 { 393 struct nand_chip *chip = (struct nand_chip *)mtd->priv; 394 struct nandsim *ns = (struct nandsim *)(chip->priv); ··· 405 } 406 } else { 407 if (ns->geom.totsz <= (128 << 20)) { 408 + ns->geom.pgaddrbytes = 4; 409 ns->geom.secaddrbytes = 2; 410 } else { 411 ns->geom.pgaddrbytes = 5; ··· 439 printk("sector address bytes: %u\n", ns->geom.secaddrbytes); 440 printk("options: %#x\n", ns->options); 441 442 + if (alloc_device(ns) != 0) 443 + goto error; 444 445 /* Allocate / initialize the internal buffer */ 446 ns->buf.byte = kmalloc(ns->geom.pgszoob, GFP_KERNEL); ··· 474 return 0; 475 476 error: 477 + free_device(ns); 478 479 return -ENOMEM; 480 } ··· 486 /* 487 * Free the nandsim structure. 488 */ 489 + static void free_nandsim(struct nandsim *ns) 490 { 491 kfree(ns->buf.byte); 492 + free_device(ns); 493 494 return; 495 } ··· 503 /* 504 * Returns the string representation of 'state' state. 505 */ 506 + static char *get_state_name(uint32_t state) 507 { 508 switch (NS_STATE(state)) { 509 case STATE_CMD_READ0: ··· 562 * 563 * RETURNS: 1 if wrong command, 0 if right. 564 */ 565 + static int check_command(int cmd) 566 { 567 switch (cmd) { 568 ··· 589 /* 590 * Returns state after command is accepted by command number. 591 */ 592 + static uint32_t get_state_by_command(unsigned command) 593 { 594 switch (command) { 595 case NAND_CMD_READ0: ··· 626 /* 627 * Move an address byte to the correspondent internal register. 628 */ 629 + static inline void accept_addr_byte(struct nandsim *ns, u_char bt) 630 { 631 uint byte = (uint)bt; 632 ··· 645 /* 646 * Switch to STATE_READY state. 647 */ 648 + static inline void switch_to_ready_state(struct nandsim *ns, u_char status) 649 { 650 NS_DBG("switch_to_ready_state: switch to %s state\n", get_state_name(STATE_READY)); 651 ··· 705 * -1 - several matches. 706 * 0 - operation is found. 707 */ 708 + static int find_operation(struct nandsim *ns, uint32_t flag) 709 { 710 int opsfound = 0; 711 int i, j, idx = 0; ··· 791 } 792 793 /* 794 + * Returns a pointer to the current page. 795 + */ 796 + static inline union ns_mem *NS_GET_PAGE(struct nandsim *ns) 797 + { 798 + return &(ns->pages[ns->regs.row]); 799 + } 800 + 801 + /* 802 + * Retuns a pointer to the current byte, within the current page. 803 + */ 804 + static inline u_char *NS_PAGE_BYTE_OFF(struct nandsim *ns) 805 + { 806 + return NS_GET_PAGE(ns)->byte + ns->regs.column + ns->regs.off; 807 + } 808 + 809 + /* 810 + * Fill the NAND buffer with data read from the specified page. 811 + */ 812 + static void read_page(struct nandsim *ns, int num) 813 + { 814 + union ns_mem *mypage; 815 + 816 + mypage = NS_GET_PAGE(ns); 817 + if (mypage->byte == NULL) { 818 + NS_DBG("read_page: page %d not allocated\n", ns->regs.row); 819 + memset(ns->buf.byte, 0xFF, num); 820 + } else { 821 + NS_DBG("read_page: page %d allocated, reading from %d\n", 822 + ns->regs.row, ns->regs.column + ns->regs.off); 823 + memcpy(ns->buf.byte, NS_PAGE_BYTE_OFF(ns), num); 824 + } 825 + } 826 + 827 + /* 828 + * Erase all pages in the specified sector. 829 + */ 830 + static void erase_sector(struct nandsim *ns) 831 + { 832 + union ns_mem *mypage; 833 + int i; 834 + 835 + mypage = NS_GET_PAGE(ns); 836 + for (i = 0; i < ns->geom.pgsec; i++) { 837 + if (mypage->byte != NULL) { 838 + NS_DBG("erase_sector: freeing page %d\n", ns->regs.row+i); 839 + kfree(mypage->byte); 840 + mypage->byte = NULL; 841 + } 842 + mypage++; 843 + } 844 + } 845 + 846 + /* 847 + * Program the specified page with the contents from the NAND buffer. 848 + */ 849 + static int prog_page(struct nandsim *ns, int num) 850 + { 851 + int i; 852 + union ns_mem *mypage; 853 + u_char *pg_off; 854 + 855 + mypage = NS_GET_PAGE(ns); 856 + if (mypage->byte == NULL) { 857 + NS_DBG("prog_page: allocating page %d\n", ns->regs.row); 858 + mypage->byte = kmalloc(ns->geom.pgszoob, GFP_KERNEL); 859 + if (mypage->byte == NULL) { 860 + NS_ERR("prog_page: error allocating memory for page %d\n", ns->regs.row); 861 + return -1; 862 + } 863 + memset(mypage->byte, 0xFF, ns->geom.pgszoob); 864 + } 865 + 866 + pg_off = NS_PAGE_BYTE_OFF(ns); 867 + for (i = 0; i < num; i++) 868 + pg_off[i] &= ns->buf.byte[i]; 869 + 870 + return 0; 871 + } 872 + 873 + /* 874 * If state has any action bit, perform this action. 875 * 876 * RETURNS: 0 if success, -1 if error. 877 */ 878 + static int do_state_action(struct nandsim *ns, uint32_t action) 879 { 880 + int num; 881 int busdiv = ns->busw == 8 ? 1 : 2; 882 883 action &= ACTION_MASK; ··· 822 break; 823 } 824 num = ns->geom.pgszoob - ns->regs.off - ns->regs.column; 825 + read_page(ns, num); 826 827 NS_DBG("do_state_action: (ACTION_CPY:) copy %d bytes to int buf, raw offset %d\n", 828 num, NS_RAW_OFFSET(ns) + ns->regs.off); ··· 863 ns->regs.row, NS_RAW_OFFSET(ns)); 864 NS_LOG("erase sector %d\n", ns->regs.row >> (ns->geom.secshift - ns->geom.pgshift)); 865 866 + erase_sector(ns); 867 868 NS_MDELAY(erase_delay); 869 ··· 886 return -1; 887 } 888 889 + if (prog_page(ns, num) == -1) 890 + return -1; 891 892 NS_DBG("do_state_action: copy %d bytes from int buf to (%#x, %#x), raw off = %d\n", 893 num, ns->regs.row, ns->regs.column, NS_RAW_OFFSET(ns) + ns->regs.off); ··· 928 /* 929 * Switch simulator's state. 930 */ 931 + static void switch_state(struct nandsim *ns) 932 { 933 if (ns->op) { 934 /* ··· 1070 } 1071 } 1072 1073 + static u_char ns_nand_read_byte(struct mtd_info *mtd) 1074 { 1075 struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv; 1076 u_char outb = 0x00; ··· 1144 return outb; 1145 } 1146 1147 + static void ns_nand_write_byte(struct mtd_info *mtd, u_char byte) 1148 { 1149 struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv; 1150 ··· 1308 ns_nand_write_byte(mtd, cmd); 1309 } 1310 1311 + static int ns_device_ready(struct mtd_info *mtd) 1312 { 1313 NS_DBG("device_ready\n"); 1314 return 1; 1315 } 1316 1317 + static uint16_t ns_nand_read_word(struct mtd_info *mtd) 1318 { 1319 struct nand_chip *chip = (struct nand_chip *)mtd->priv; 1320 ··· 1325 return chip->read_byte(mtd) | (chip->read_byte(mtd) << 8); 1326 } 1327 1328 + static void ns_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) 1329 { 1330 struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv; 1331 ··· 1353 } 1354 } 1355 1356 + static void ns_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) 1357 { 1358 struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv; 1359 ··· 1407 return; 1408 } 1409 1410 + static int ns_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len) 1411 { 1412 ns_nand_read_buf(mtd, (u_char *)&ns_verify_buf[0], len); 1413 ··· 1436 } 1437 1438 /* Allocate and initialize mtd_info, nand_chip and nandsim structures */ 1439 + nsmtd = kzalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip) 1440 + sizeof(struct nandsim), GFP_KERNEL); 1441 if (!nsmtd) { 1442 NS_ERR("unable to allocate core structures.\n"); 1443 return -ENOMEM; 1444 } 1445 chip = (struct nand_chip *)(nsmtd + 1); 1446 nsmtd->priv = (void *)chip; 1447 nand = (struct nandsim *)(chip + 1);
+1 -1
drivers/mtd/nand/ndfc.c
··· 56 ccr |= NDFC_CCR_BS(chip + pchip->chip_offset); 57 } else 58 ccr |= NDFC_CCR_RESET_CE; 59 - writel(ccr, ndfc->ndfcbase + NDFC_CCR); 60 } 61 62 static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
··· 56 ccr |= NDFC_CCR_BS(chip + pchip->chip_offset); 57 } else 58 ccr |= NDFC_CCR_RESET_CE; 59 + __raw_writel(ccr, ndfc->ndfcbase + NDFC_CCR); 60 } 61 62 static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
+3 -43
drivers/mtd/nand/rtc_from4.c
··· 24 #include <linux/init.h> 25 #include <linux/slab.h> 26 #include <linux/rslib.h> 27 #include <linux/module.h> 28 #include <linux/mtd/compatmac.h> 29 #include <linux/mtd/mtd.h> ··· 151 16, 17, 18, 19, 20, 21, 22, 23, 152 24, 25, 26, 27, 28, 29, 30, 31}, 153 .oobfree = {{32, 32}} 154 - }; 155 - 156 - /* Aargh. I missed the reversed bit order, when I 157 - * was talking to Renesas about the FPGA. 158 - * 159 - * The table is used for bit reordering and inversion 160 - * of the ecc byte which we get from the FPGA 161 - */ 162 - static uint8_t revbits[256] = { 163 - 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 164 - 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, 165 - 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 166 - 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 167 - 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 168 - 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, 169 - 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 170 - 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, 171 - 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 172 - 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, 173 - 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, 174 - 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, 175 - 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 176 - 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, 177 - 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 178 - 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, 179 - 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, 180 - 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, 181 - 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 182 - 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, 183 - 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 184 - 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, 185 - 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 186 - 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, 187 - 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 188 - 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, 189 - 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 190 - 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, 191 - 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 192 - 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, 193 - 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 194 - 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff, 195 }; 196 197 #endif ··· 357 /* Read the syndrom pattern from the FPGA and correct the bitorder */ 358 rs_ecc = (volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_RS_ECC); 359 for (i = 0; i < 8; i++) { 360 - ecc[i] = revbits[(*rs_ecc) & 0xFF]; 361 rs_ecc++; 362 } 363 ··· 456 rtn = nand_do_read(mtd, page, len, &retlen, buf); 457 458 /* if read failed or > 1-bit error corrected */ 459 - if (rtn || (mtd->ecc_stats.corrected - corrected) > 1) { 460 er_stat |= 1 << 1; 461 kfree(buf); 462 }
··· 24 #include <linux/init.h> 25 #include <linux/slab.h> 26 #include <linux/rslib.h> 27 + #include <linux/bitrev.h> 28 #include <linux/module.h> 29 #include <linux/mtd/compatmac.h> 30 #include <linux/mtd/mtd.h> ··· 150 16, 17, 18, 19, 20, 21, 22, 23, 151 24, 25, 26, 27, 28, 29, 30, 31}, 152 .oobfree = {{32, 32}} 153 }; 154 155 #endif ··· 397 /* Read the syndrom pattern from the FPGA and correct the bitorder */ 398 rs_ecc = (volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_RS_ECC); 399 for (i = 0; i < 8; i++) { 400 + ecc[i] = bitrev8(*rs_ecc); 401 rs_ecc++; 402 } 403 ··· 496 rtn = nand_do_read(mtd, page, len, &retlen, buf); 497 498 /* if read failed or > 1-bit error corrected */ 499 + if (rtn || (mtd->ecc_stats.corrected - corrected) > 1) 500 er_stat |= 1 << 1; 501 kfree(buf); 502 }
+1 -1
drivers/mtd/nand/s3c2410.c
··· 283 unsigned int ctrl) 284 { 285 struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd); 286 - 287 if (cmd == NAND_CMD_NONE) 288 return; 289
··· 283 unsigned int ctrl) 284 { 285 struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd); 286 + 287 if (cmd == NAND_CMD_NONE) 288 return; 289
+5 -7
drivers/mtd/nftlcore.c
··· 57 58 DEBUG(MTD_DEBUG_LEVEL1, "NFTL: add_mtd for %s\n", mtd->name); 59 60 - nftl = kmalloc(sizeof(struct NFTLrecord), GFP_KERNEL); 61 62 if (!nftl) { 63 printk(KERN_WARNING "NFTL: out of memory for data structures\n"); 64 return; 65 } 66 - memset(nftl, 0, sizeof(*nftl)); 67 68 nftl->mbd.mtd = mtd; 69 nftl->mbd.devnum = -1; 70 - nftl->mbd.blksize = 512; 71 nftl->mbd.tr = tr; 72 73 if (NFTL_mount(nftl) < 0) { ··· 146 ops.ooblen = len; 147 ops.oobbuf = buf; 148 ops.datbuf = NULL; 149 - ops.len = len; 150 151 res = mtd->read_oob(mtd, offs & ~(mtd->writesize - 1), &ops); 152 - *retlen = ops.retlen; 153 return res; 154 } 155 ··· 166 ops.ooblen = len; 167 ops.oobbuf = buf; 168 ops.datbuf = NULL; 169 - ops.len = len; 170 171 res = mtd->write_oob(mtd, offs & ~(mtd->writesize - 1), &ops); 172 - *retlen = ops.retlen; 173 return res; 174 } 175 ··· 794 .name = "nftl", 795 .major = NFTL_MAJOR, 796 .part_bits = NFTL_PARTN_BITS, 797 .getgeo = nftl_getgeo, 798 .readsect = nftl_readblock, 799 #ifdef CONFIG_NFTL_RW
··· 57 58 DEBUG(MTD_DEBUG_LEVEL1, "NFTL: add_mtd for %s\n", mtd->name); 59 60 + nftl = kzalloc(sizeof(struct NFTLrecord), GFP_KERNEL); 61 62 if (!nftl) { 63 printk(KERN_WARNING "NFTL: out of memory for data structures\n"); 64 return; 65 } 66 67 nftl->mbd.mtd = mtd; 68 nftl->mbd.devnum = -1; 69 + 70 nftl->mbd.tr = tr; 71 72 if (NFTL_mount(nftl) < 0) { ··· 147 ops.ooblen = len; 148 ops.oobbuf = buf; 149 ops.datbuf = NULL; 150 151 res = mtd->read_oob(mtd, offs & ~(mtd->writesize - 1), &ops); 152 + *retlen = ops.oobretlen; 153 return res; 154 } 155 ··· 168 ops.ooblen = len; 169 ops.oobbuf = buf; 170 ops.datbuf = NULL; 171 172 res = mtd->write_oob(mtd, offs & ~(mtd->writesize - 1), &ops); 173 + *retlen = ops.oobretlen; 174 return res; 175 } 176 ··· 797 .name = "nftl", 798 .major = NFTL_MAJOR, 799 .part_bits = NFTL_PARTN_BITS, 800 + .blksize = 512, 801 .getgeo = nftl_getgeo, 802 .readsect = nftl_readblock, 803 #ifdef CONFIG_NFTL_RW
+2 -3
drivers/mtd/onenand/generic.c
··· 45 unsigned long size = res->end - res->start + 1; 46 int err; 47 48 - info = kmalloc(sizeof(struct onenand_info), GFP_KERNEL); 49 if (!info) 50 return -ENOMEM; 51 - 52 - memset(info, 0, sizeof(struct onenand_info)); 53 54 if (!request_mem_region(res->start, size, dev->driver->name)) { 55 err = -EBUSY; ··· 61 } 62 63 info->onenand.mmcontrol = pdata->mmcontrol; 64 65 info->mtd.name = pdev->dev.bus_id; 66 info->mtd.priv = &info->onenand;
··· 45 unsigned long size = res->end - res->start + 1; 46 int err; 47 48 + info = kzalloc(sizeof(struct onenand_info), GFP_KERNEL); 49 if (!info) 50 return -ENOMEM; 51 52 if (!request_mem_region(res->start, size, dev->driver->name)) { 53 err = -EBUSY; ··· 63 } 64 65 info->onenand.mmcontrol = pdata->mmcontrol; 66 + info->onenand.irq = platform_get_irq(pdev, 0); 67 68 info->mtd.name = pdev->dev.bus_id; 69 info->mtd.priv = &info->onenand;
+281 -89
drivers/mtd/onenand/onenand_base.c
··· 13 #include <linux/module.h> 14 #include <linux/init.h> 15 #include <linux/sched.h> 16 #include <linux/jiffies.h> 17 #include <linux/mtd/mtd.h> 18 #include <linux/mtd/onenand.h> ··· 192 struct onenand_chip *this = mtd->priv; 193 int value, readcmd = 0, block_cmd = 0; 194 int block, page; 195 - /* Now we use page size operation */ 196 - int sectors = 4, count = 4; 197 198 /* Address translation */ 199 switch (cmd) { ··· 243 } 244 245 if (page != -1) { 246 int dataram; 247 248 switch (cmd) { ··· 298 unsigned long timeout; 299 unsigned int flags = ONENAND_INT_MASTER; 300 unsigned int interrupt = 0; 301 - unsigned int ctrl, ecc; 302 303 /* The 20 msec is enough */ 304 timeout = jiffies + msecs_to_jiffies(20); ··· 310 311 if (state != FL_READING) 312 cond_resched(); 313 - touch_softlockup_watchdog(); 314 } 315 /* To get correct interrupt status in timeout case */ 316 interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT); ··· 317 ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS); 318 319 if (ctrl & ONENAND_CTRL_ERROR) { 320 - /* It maybe occur at initial bad block */ 321 DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: controller error = 0x%04x\n", ctrl); 322 - /* Clear other interrupt bits for preventing ECC error */ 323 - interrupt &= ONENAND_INT_MASTER; 324 - } 325 - 326 - if (ctrl & ONENAND_CTRL_LOCK) { 327 - DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: it's locked error = 0x%04x\n", ctrl); 328 - return -EACCES; 329 } 330 331 if (interrupt & ONENAND_INT_READ) { 332 - ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS); 333 - if (ecc & ONENAND_ECC_2BIT_ALL) { 334 DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: ECC error = 0x%04x\n", ecc); 335 - return -EBADMSG; 336 } 337 } 338 339 return 0; 340 } 341 342 /** ··· 707 size_t *retlen, u_char *buf) 708 { 709 struct onenand_chip *this = mtd->priv; 710 int read = 0, column; 711 int thislen; 712 - int ret = 0; 713 714 DEBUG(MTD_DEBUG_LEVEL3, "onenand_read: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len); 715 ··· 726 727 /* TODO handling oob */ 728 729 - while (read < len) { 730 - thislen = min_t(int, mtd->writesize, len - read); 731 732 - column = from & (mtd->writesize - 1); 733 - if (column + thislen > mtd->writesize) 734 - thislen = mtd->writesize - column; 735 736 - if (!onenand_check_bufferram(mtd, from)) { 737 - this->command(mtd, ONENAND_CMD_READ, from, mtd->writesize); 738 739 - ret = this->wait(mtd, FL_READING); 740 - /* First copy data and check return value for ECC handling */ 741 - onenand_update_bufferram(mtd, from, 1); 742 - } 743 744 - this->read_bufferram(mtd, ONENAND_DATARAM, buf, column, thislen); 745 746 - read += thislen; 747 - 748 - if (read == len) 749 - break; 750 - 751 - if (ret) { 752 - DEBUG(MTD_DEBUG_LEVEL0, "onenand_read: read failed = %d\n", ret); 753 - goto out; 754 - } 755 - 756 - from += thislen; 757 - buf += thislen; 758 - } 759 - 760 - out: 761 /* Deselect and wake up anyone waiting on the device */ 762 onenand_release_device(mtd); 763 ··· 790 * retlen == desired len and result == -EBADMSG 791 */ 792 *retlen = read; 793 - return ret; 794 } 795 796 /** ··· 834 column = from & (mtd->oobsize - 1); 835 836 while (read < len) { 837 thislen = mtd->oobsize - column; 838 thislen = min_t(int, thislen, len); 839 ··· 848 849 this->read_bufferram(mtd, ONENAND_SPARERAM, buf, column, thislen); 850 851 read += thislen; 852 853 if (read == len) 854 break; 855 - 856 - if (ret) { 857 - DEBUG(MTD_DEBUG_LEVEL0, "onenand_read_oob: read failed = %d\n", ret); 858 - goto out; 859 - } 860 861 buf += thislen; 862 ··· 887 { 888 BUG_ON(ops->mode != MTD_OOB_PLACE); 889 890 - return onenand_do_read_oob(mtd, from + ops->ooboffs, ops->len, 891 - &ops->retlen, ops->oobbuf); 892 } 893 894 #ifdef CONFIG_MTD_ONENAND_VERIFY_WRITE ··· 935 void __iomem *dataram0, *dataram1; 936 int ret = 0; 937 938 this->command(mtd, ONENAND_CMD_READ, addr, mtd->writesize); 939 940 ret = this->wait(mtd, FL_READING); ··· 961 #define onenand_verify_oob(...) (0) 962 #endif 963 964 - #define NOTALIGNED(x) ((x & (mtd->writesize - 1)) != 0) 965 966 /** 967 * onenand_write - [MTD Interface] write buffer to FLASH ··· 979 struct onenand_chip *this = mtd->priv; 980 int written = 0; 981 int ret = 0; 982 983 DEBUG(MTD_DEBUG_LEVEL3, "onenand_write: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len); 984 ··· 998 return -EINVAL; 999 } 1000 1001 /* Grab the lock and see if the device is available */ 1002 onenand_get_device(mtd, FL_WRITING); 1003 1004 /* Loop until all data write */ 1005 while (written < len) { 1006 - int thislen = min_t(int, mtd->writesize, len - written); 1007 1008 - this->command(mtd, ONENAND_CMD_BUFFERRAM, to, mtd->writesize); 1009 1010 - this->write_bufferram(mtd, ONENAND_DATARAM, buf, 0, thislen); 1011 this->write_bufferram(mtd, ONENAND_SPARERAM, ffchars, 0, mtd->oobsize); 1012 1013 this->command(mtd, ONENAND_CMD_PROG, to, mtd->writesize); 1014 1015 - onenand_update_bufferram(mtd, to, 1); 1016 1017 ret = this->wait(mtd, FL_WRITING); 1018 if (ret) { 1019 DEBUG(MTD_DEBUG_LEVEL0, "onenand_write: write filaed %d\n", ret); 1020 - goto out; 1021 } 1022 1023 written += thislen; 1024 1025 - /* Only check verify write turn on */ 1026 - ret = onenand_verify_page(mtd, (u_char *) buf, to); 1027 - if (ret) { 1028 - DEBUG(MTD_DEBUG_LEVEL0, "onenand_write: verify failed %d\n", ret); 1029 - goto out; 1030 - } 1031 - 1032 if (written == len) 1033 break; 1034 1035 to += thislen; 1036 buf += thislen; 1037 } 1038 1039 - out: 1040 /* Deselect and wake up anyone waiting on the device */ 1041 onenand_release_device(mtd); 1042 ··· 1097 /* Loop until all data write */ 1098 while (written < len) { 1099 int thislen = min_t(int, mtd->oobsize, len - written); 1100 1101 column = to & (mtd->oobsize - 1); 1102 ··· 1155 { 1156 BUG_ON(ops->mode != MTD_OOB_PLACE); 1157 1158 - return onenand_do_write_oob(mtd, to + ops->ooboffs, ops->len, 1159 - &ops->retlen, ops->oobbuf); 1160 } 1161 1162 /** ··· 1227 instr->state = MTD_ERASING; 1228 1229 while (len) { 1230 1231 /* Check if we have a bad block, we do not erase bad blocks */ 1232 if (onenand_block_checkbad(mtd, addr, 0, 0)) { ··· 1241 ret = this->wait(mtd, FL_ERASING); 1242 /* Check, if it is write protected */ 1243 if (ret) { 1244 - if (ret == -EPERM) 1245 - DEBUG(MTD_DEBUG_LEVEL0, "onenand_erase: Device is write protected!!!\n"); 1246 - else 1247 - DEBUG(MTD_DEBUG_LEVEL0, "onenand_erase: Failed erase, block %d\n", (unsigned) (addr >> this->erase_shift)); 1248 instr->state = MTD_ERASE_FAILED; 1249 instr->fail_addr = addr; 1250 goto erase_exit; ··· 1282 /* Release it and go back */ 1283 onenand_release_device(mtd); 1284 } 1285 - 1286 1287 /** 1288 * onenand_block_isbad - [MTD Interface] Check whether the block at the given offset is bad ··· 1349 } 1350 1351 /** 1352 - * onenand_unlock - [MTD Interface] Unlock block(s) 1353 * @param mtd MTD device structure 1354 * @param ofs offset relative to mtd start 1355 - * @param len number of bytes to unlock 1356 * 1357 - * Unlock one or more blocks 1358 */ 1359 - static int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len) 1360 { 1361 struct onenand_chip *this = mtd->priv; 1362 int start, end, block, value, status; 1363 1364 start = ofs >> this->erase_shift; 1365 end = len >> this->erase_shift; 1366 1367 /* Continuous lock scheme */ 1368 if (this->options & ONENAND_HAS_CONT_LOCK) { ··· 1376 this->write_word(start, this->base + ONENAND_REG_START_BLOCK_ADDRESS); 1377 /* Set end block address */ 1378 this->write_word(start + end - 1, this->base + ONENAND_REG_END_BLOCK_ADDRESS); 1379 - /* Write unlock command */ 1380 - this->command(mtd, ONENAND_CMD_UNLOCK, 0, 0); 1381 1382 /* There's no return value */ 1383 - this->wait(mtd, FL_UNLOCKING); 1384 1385 /* Sanity check */ 1386 while (this->read_word(this->base + ONENAND_REG_CTRL_STATUS) ··· 1389 1390 /* Check lock status */ 1391 status = this->read_word(this->base + ONENAND_REG_WP_STATUS); 1392 - if (!(status & ONENAND_WP_US)) 1393 printk(KERN_ERR "wp status = 0x%x\n", status); 1394 1395 return 0; ··· 1405 this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2); 1406 /* Set start block address */ 1407 this->write_word(block, this->base + ONENAND_REG_START_BLOCK_ADDRESS); 1408 - /* Write unlock command */ 1409 - this->command(mtd, ONENAND_CMD_UNLOCK, 0, 0); 1410 1411 /* There's no return value */ 1412 - this->wait(mtd, FL_UNLOCKING); 1413 1414 /* Sanity check */ 1415 while (this->read_word(this->base + ONENAND_REG_CTRL_STATUS) ··· 1418 1419 /* Check lock status */ 1420 status = this->read_word(this->base + ONENAND_REG_WP_STATUS); 1421 - if (!(status & ONENAND_WP_US)) 1422 printk(KERN_ERR "block = %d, wp status = 0x%x\n", block, status); 1423 } 1424 1425 return 0; 1426 } 1427 1428 /** ··· 1495 this->command(mtd, ONENAND_CMD_UNLOCK_ALL, 0, 0); 1496 1497 /* There's no return value */ 1498 - this->wait(mtd, FL_UNLOCKING); 1499 1500 /* Sanity check */ 1501 while (this->read_word(this->base + ONENAND_REG_CTRL_STATUS) ··· 1519 return 0; 1520 } 1521 1522 - mtd->unlock(mtd, 0x0, this->chipsize); 1523 1524 return 0; 1525 } ··· 1947 /* Read manufacturer and device IDs from Register */ 1948 maf_id = this->read_word(this->base + ONENAND_REG_MANUFACTURER_ID); 1949 dev_id = this->read_word(this->base + ONENAND_REG_DEVICE_ID); 1950 - ver_id= this->read_word(this->base + ONENAND_REG_VERSION_ID); 1951 1952 /* Check OneNAND device */ 1953 if (maf_id != bram_maf_id || dev_id != bram_dev_id) ··· 2031 if (!this->command) 2032 this->command = onenand_command; 2033 if (!this->wait) 2034 - this->wait = onenand_wait; 2035 2036 if (!this->read_bufferram) 2037 this->read_bufferram = onenand_read_bufferram; ··· 2068 init_waitqueue_head(&this->wq); 2069 spin_lock_init(&this->chip_lock); 2070 2071 switch (mtd->oobsize) { 2072 case 64: 2073 this->ecclayout = &onenand_oob_64; 2074 break; 2075 2076 case 32: 2077 this->ecclayout = &onenand_oob_32; 2078 break; 2079 2080 default: 2081 printk(KERN_WARNING "No OOB scheme defined for oobsize %d\n", 2082 mtd->oobsize); 2083 /* To prevent kernel oops */ 2084 this->ecclayout = &onenand_oob_32; 2085 break; 2086 } 2087 2088 mtd->ecclayout = this->ecclayout; 2089 2090 /* Fill in remaining MTD driver data */ ··· 2114 mtd->lock_user_prot_reg = onenand_lock_user_prot_reg; 2115 #endif 2116 mtd->sync = onenand_sync; 2117 - mtd->lock = NULL; 2118 mtd->unlock = onenand_unlock; 2119 mtd->suspend = onenand_suspend; 2120 mtd->resume = onenand_resume;
··· 13 #include <linux/module.h> 14 #include <linux/init.h> 15 #include <linux/sched.h> 16 + #include <linux/interrupt.h> 17 #include <linux/jiffies.h> 18 #include <linux/mtd/mtd.h> 19 #include <linux/mtd/onenand.h> ··· 191 struct onenand_chip *this = mtd->priv; 192 int value, readcmd = 0, block_cmd = 0; 193 int block, page; 194 195 /* Address translation */ 196 switch (cmd) { ··· 244 } 245 246 if (page != -1) { 247 + /* Now we use page size operation */ 248 + int sectors = 4, count = 4; 249 int dataram; 250 251 switch (cmd) { ··· 297 unsigned long timeout; 298 unsigned int flags = ONENAND_INT_MASTER; 299 unsigned int interrupt = 0; 300 + unsigned int ctrl; 301 302 /* The 20 msec is enough */ 303 timeout = jiffies + msecs_to_jiffies(20); ··· 309 310 if (state != FL_READING) 311 cond_resched(); 312 } 313 /* To get correct interrupt status in timeout case */ 314 interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT); ··· 317 ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS); 318 319 if (ctrl & ONENAND_CTRL_ERROR) { 320 DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: controller error = 0x%04x\n", ctrl); 321 + if (ctrl & ONENAND_CTRL_LOCK) 322 + DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: it's locked error.\n"); 323 + return ctrl; 324 } 325 326 if (interrupt & ONENAND_INT_READ) { 327 + int ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS); 328 + if (ecc) { 329 DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: ECC error = 0x%04x\n", ecc); 330 + if (ecc & ONENAND_ECC_2BIT_ALL) { 331 + mtd->ecc_stats.failed++; 332 + return ecc; 333 + } else if (ecc & ONENAND_ECC_1BIT_ALL) 334 + mtd->ecc_stats.corrected++; 335 } 336 } 337 338 return 0; 339 + } 340 + 341 + /* 342 + * onenand_interrupt - [DEFAULT] onenand interrupt handler 343 + * @param irq onenand interrupt number 344 + * @param dev_id interrupt data 345 + * 346 + * complete the work 347 + */ 348 + static irqreturn_t onenand_interrupt(int irq, void *data) 349 + { 350 + struct onenand_chip *this = (struct onenand_chip *) data; 351 + 352 + /* To handle shared interrupt */ 353 + if (!this->complete.done) 354 + complete(&this->complete); 355 + 356 + return IRQ_HANDLED; 357 + } 358 + 359 + /* 360 + * onenand_interrupt_wait - [DEFAULT] wait until the command is done 361 + * @param mtd MTD device structure 362 + * @param state state to select the max. timeout value 363 + * 364 + * Wait for command done. 365 + */ 366 + static int onenand_interrupt_wait(struct mtd_info *mtd, int state) 367 + { 368 + struct onenand_chip *this = mtd->priv; 369 + 370 + wait_for_completion(&this->complete); 371 + 372 + return onenand_wait(mtd, state); 373 + } 374 + 375 + /* 376 + * onenand_try_interrupt_wait - [DEFAULT] try interrupt wait 377 + * @param mtd MTD device structure 378 + * @param state state to select the max. timeout value 379 + * 380 + * Try interrupt based wait (It is used one-time) 381 + */ 382 + static int onenand_try_interrupt_wait(struct mtd_info *mtd, int state) 383 + { 384 + struct onenand_chip *this = mtd->priv; 385 + unsigned long remain, timeout; 386 + 387 + /* We use interrupt wait first */ 388 + this->wait = onenand_interrupt_wait; 389 + 390 + timeout = msecs_to_jiffies(100); 391 + remain = wait_for_completion_timeout(&this->complete, timeout); 392 + if (!remain) { 393 + printk(KERN_INFO "OneNAND: There's no interrupt. " 394 + "We use the normal wait\n"); 395 + 396 + /* Release the irq */ 397 + free_irq(this->irq, this); 398 + 399 + this->wait = onenand_wait; 400 + } 401 + 402 + return onenand_wait(mtd, state); 403 + } 404 + 405 + /* 406 + * onenand_setup_wait - [OneNAND Interface] setup onenand wait method 407 + * @param mtd MTD device structure 408 + * 409 + * There's two method to wait onenand work 410 + * 1. polling - read interrupt status register 411 + * 2. interrupt - use the kernel interrupt method 412 + */ 413 + static void onenand_setup_wait(struct mtd_info *mtd) 414 + { 415 + struct onenand_chip *this = mtd->priv; 416 + int syscfg; 417 + 418 + init_completion(&this->complete); 419 + 420 + if (this->irq <= 0) { 421 + this->wait = onenand_wait; 422 + return; 423 + } 424 + 425 + if (request_irq(this->irq, &onenand_interrupt, 426 + IRQF_SHARED, "onenand", this)) { 427 + /* If we can't get irq, use the normal wait */ 428 + this->wait = onenand_wait; 429 + return; 430 + } 431 + 432 + /* Enable interrupt */ 433 + syscfg = this->read_word(this->base + ONENAND_REG_SYS_CFG1); 434 + syscfg |= ONENAND_SYS_CFG1_IOBE; 435 + this->write_word(syscfg, this->base + ONENAND_REG_SYS_CFG1); 436 + 437 + this->wait = onenand_try_interrupt_wait; 438 } 439 440 /** ··· 609 size_t *retlen, u_char *buf) 610 { 611 struct onenand_chip *this = mtd->priv; 612 + struct mtd_ecc_stats stats; 613 int read = 0, column; 614 int thislen; 615 + int ret = 0, boundary = 0; 616 617 DEBUG(MTD_DEBUG_LEVEL3, "onenand_read: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len); 618 ··· 627 628 /* TODO handling oob */ 629 630 + stats = mtd->ecc_stats; 631 632 + /* Read-while-load method */ 633 634 + /* Do first load to bufferRAM */ 635 + if (read < len) { 636 + if (!onenand_check_bufferram(mtd, from)) { 637 + this->command(mtd, ONENAND_CMD_READ, from, mtd->writesize); 638 + ret = this->wait(mtd, FL_READING); 639 + onenand_update_bufferram(mtd, from, !ret); 640 + } 641 + } 642 643 + thislen = min_t(int, mtd->writesize, len - read); 644 + column = from & (mtd->writesize - 1); 645 + if (column + thislen > mtd->writesize) 646 + thislen = mtd->writesize - column; 647 648 + while (!ret) { 649 + /* If there is more to load then start next load */ 650 + from += thislen; 651 + if (read + thislen < len) { 652 + this->command(mtd, ONENAND_CMD_READ, from, mtd->writesize); 653 + /* 654 + * Chip boundary handling in DDP 655 + * Now we issued chip 1 read and pointed chip 1 656 + * bufferam so we have to point chip 0 bufferam. 657 + */ 658 + if (this->device_id & ONENAND_DEVICE_IS_DDP && 659 + unlikely(from == (this->chipsize >> 1))) { 660 + this->write_word(0, this->base + ONENAND_REG_START_ADDRESS2); 661 + boundary = 1; 662 + } else 663 + boundary = 0; 664 + ONENAND_SET_PREV_BUFFERRAM(this); 665 + } 666 + /* While load is going, read from last bufferRAM */ 667 + this->read_bufferram(mtd, ONENAND_DATARAM, buf, column, thislen); 668 + /* See if we are done */ 669 + read += thislen; 670 + if (read == len) 671 + break; 672 + /* Set up for next read from bufferRAM */ 673 + if (unlikely(boundary)) 674 + this->write_word(0x8000, this->base + ONENAND_REG_START_ADDRESS2); 675 + ONENAND_SET_NEXT_BUFFERRAM(this); 676 + buf += thislen; 677 + thislen = min_t(int, mtd->writesize, len - read); 678 + column = 0; 679 + cond_resched(); 680 + /* Now wait for load */ 681 + ret = this->wait(mtd, FL_READING); 682 + onenand_update_bufferram(mtd, from, !ret); 683 + } 684 685 /* Deselect and wake up anyone waiting on the device */ 686 onenand_release_device(mtd); 687 ··· 668 * retlen == desired len and result == -EBADMSG 669 */ 670 *retlen = read; 671 + 672 + if (mtd->ecc_stats.failed - stats.failed) 673 + return -EBADMSG; 674 + 675 + if (ret) 676 + return ret; 677 + 678 + return mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0; 679 } 680 681 /** ··· 705 column = from & (mtd->oobsize - 1); 706 707 while (read < len) { 708 + cond_resched(); 709 + 710 thislen = mtd->oobsize - column; 711 thislen = min_t(int, thislen, len); 712 ··· 717 718 this->read_bufferram(mtd, ONENAND_SPARERAM, buf, column, thislen); 719 720 + if (ret) { 721 + DEBUG(MTD_DEBUG_LEVEL0, "onenand_read_oob: read failed = 0x%x\n", ret); 722 + goto out; 723 + } 724 + 725 read += thislen; 726 727 if (read == len) 728 break; 729 730 buf += thislen; 731 ··· 756 { 757 BUG_ON(ops->mode != MTD_OOB_PLACE); 758 759 + return onenand_do_read_oob(mtd, from + ops->ooboffs, ops->ooblen, 760 + &ops->oobretlen, ops->oobbuf); 761 } 762 763 #ifdef CONFIG_MTD_ONENAND_VERIFY_WRITE ··· 804 void __iomem *dataram0, *dataram1; 805 int ret = 0; 806 807 + /* In partial page write, just skip it */ 808 + if ((addr & (mtd->writesize - 1)) != 0) 809 + return 0; 810 + 811 this->command(mtd, ONENAND_CMD_READ, addr, mtd->writesize); 812 813 ret = this->wait(mtd, FL_READING); ··· 826 #define onenand_verify_oob(...) (0) 827 #endif 828 829 + #define NOTALIGNED(x) ((x & (this->subpagesize - 1)) != 0) 830 831 /** 832 * onenand_write - [MTD Interface] write buffer to FLASH ··· 844 struct onenand_chip *this = mtd->priv; 845 int written = 0; 846 int ret = 0; 847 + int column, subpage; 848 849 DEBUG(MTD_DEBUG_LEVEL3, "onenand_write: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len); 850 ··· 862 return -EINVAL; 863 } 864 865 + column = to & (mtd->writesize - 1); 866 + subpage = column || (len & (mtd->writesize - 1)); 867 + 868 /* Grab the lock and see if the device is available */ 869 onenand_get_device(mtd, FL_WRITING); 870 871 /* Loop until all data write */ 872 while (written < len) { 873 + int bytes = mtd->writesize; 874 + int thislen = min_t(int, bytes, len - written); 875 + u_char *wbuf = (u_char *) buf; 876 877 + cond_resched(); 878 879 + this->command(mtd, ONENAND_CMD_BUFFERRAM, to, bytes); 880 + 881 + /* Partial page write */ 882 + if (subpage) { 883 + bytes = min_t(int, bytes - column, (int) len); 884 + memset(this->page_buf, 0xff, mtd->writesize); 885 + memcpy(this->page_buf + column, buf, bytes); 886 + wbuf = this->page_buf; 887 + /* Even though partial write, we need page size */ 888 + thislen = mtd->writesize; 889 + } 890 + 891 + this->write_bufferram(mtd, ONENAND_DATARAM, wbuf, 0, thislen); 892 this->write_bufferram(mtd, ONENAND_SPARERAM, ffchars, 0, mtd->oobsize); 893 894 this->command(mtd, ONENAND_CMD_PROG, to, mtd->writesize); 895 896 + /* In partial page write we don't update bufferram */ 897 + onenand_update_bufferram(mtd, to, !subpage); 898 899 ret = this->wait(mtd, FL_WRITING); 900 if (ret) { 901 DEBUG(MTD_DEBUG_LEVEL0, "onenand_write: write filaed %d\n", ret); 902 + break; 903 + } 904 + 905 + /* Only check verify write turn on */ 906 + ret = onenand_verify_page(mtd, (u_char *) wbuf, to); 907 + if (ret) { 908 + DEBUG(MTD_DEBUG_LEVEL0, "onenand_write: verify failed %d\n", ret); 909 + break; 910 } 911 912 written += thislen; 913 914 if (written == len) 915 break; 916 917 + column = 0; 918 to += thislen; 919 buf += thislen; 920 } 921 922 /* Deselect and wake up anyone waiting on the device */ 923 onenand_release_device(mtd); 924 ··· 943 /* Loop until all data write */ 944 while (written < len) { 945 int thislen = min_t(int, mtd->oobsize, len - written); 946 + 947 + cond_resched(); 948 949 column = to & (mtd->oobsize - 1); 950 ··· 999 { 1000 BUG_ON(ops->mode != MTD_OOB_PLACE); 1001 1002 + return onenand_do_write_oob(mtd, to + ops->ooboffs, ops->ooblen, 1003 + &ops->oobretlen, ops->oobbuf); 1004 } 1005 1006 /** ··· 1071 instr->state = MTD_ERASING; 1072 1073 while (len) { 1074 + cond_resched(); 1075 1076 /* Check if we have a bad block, we do not erase bad blocks */ 1077 if (onenand_block_checkbad(mtd, addr, 0, 0)) { ··· 1084 ret = this->wait(mtd, FL_ERASING); 1085 /* Check, if it is write protected */ 1086 if (ret) { 1087 + DEBUG(MTD_DEBUG_LEVEL0, "onenand_erase: Failed erase, block %d\n", (unsigned) (addr >> this->erase_shift)); 1088 instr->state = MTD_ERASE_FAILED; 1089 instr->fail_addr = addr; 1090 goto erase_exit; ··· 1128 /* Release it and go back */ 1129 onenand_release_device(mtd); 1130 } 1131 1132 /** 1133 * onenand_block_isbad - [MTD Interface] Check whether the block at the given offset is bad ··· 1196 } 1197 1198 /** 1199 + * onenand_do_lock_cmd - [OneNAND Interface] Lock or unlock block(s) 1200 * @param mtd MTD device structure 1201 * @param ofs offset relative to mtd start 1202 + * @param len number of bytes to lock or unlock 1203 * 1204 + * Lock or unlock one or more blocks 1205 */ 1206 + static int onenand_do_lock_cmd(struct mtd_info *mtd, loff_t ofs, size_t len, int cmd) 1207 { 1208 struct onenand_chip *this = mtd->priv; 1209 int start, end, block, value, status; 1210 + int wp_status_mask; 1211 1212 start = ofs >> this->erase_shift; 1213 end = len >> this->erase_shift; 1214 + 1215 + if (cmd == ONENAND_CMD_LOCK) 1216 + wp_status_mask = ONENAND_WP_LS; 1217 + else 1218 + wp_status_mask = ONENAND_WP_US; 1219 1220 /* Continuous lock scheme */ 1221 if (this->options & ONENAND_HAS_CONT_LOCK) { ··· 1217 this->write_word(start, this->base + ONENAND_REG_START_BLOCK_ADDRESS); 1218 /* Set end block address */ 1219 this->write_word(start + end - 1, this->base + ONENAND_REG_END_BLOCK_ADDRESS); 1220 + /* Write lock command */ 1221 + this->command(mtd, cmd, 0, 0); 1222 1223 /* There's no return value */ 1224 + this->wait(mtd, FL_LOCKING); 1225 1226 /* Sanity check */ 1227 while (this->read_word(this->base + ONENAND_REG_CTRL_STATUS) ··· 1230 1231 /* Check lock status */ 1232 status = this->read_word(this->base + ONENAND_REG_WP_STATUS); 1233 + if (!(status & wp_status_mask)) 1234 printk(KERN_ERR "wp status = 0x%x\n", status); 1235 1236 return 0; ··· 1246 this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2); 1247 /* Set start block address */ 1248 this->write_word(block, this->base + ONENAND_REG_START_BLOCK_ADDRESS); 1249 + /* Write lock command */ 1250 + this->command(mtd, cmd, 0, 0); 1251 1252 /* There's no return value */ 1253 + this->wait(mtd, FL_LOCKING); 1254 1255 /* Sanity check */ 1256 while (this->read_word(this->base + ONENAND_REG_CTRL_STATUS) ··· 1259 1260 /* Check lock status */ 1261 status = this->read_word(this->base + ONENAND_REG_WP_STATUS); 1262 + if (!(status & wp_status_mask)) 1263 printk(KERN_ERR "block = %d, wp status = 0x%x\n", block, status); 1264 } 1265 1266 return 0; 1267 + } 1268 + 1269 + /** 1270 + * onenand_lock - [MTD Interface] Lock block(s) 1271 + * @param mtd MTD device structure 1272 + * @param ofs offset relative to mtd start 1273 + * @param len number of bytes to unlock 1274 + * 1275 + * Lock one or more blocks 1276 + */ 1277 + static int onenand_lock(struct mtd_info *mtd, loff_t ofs, size_t len) 1278 + { 1279 + return onenand_do_lock_cmd(mtd, ofs, len, ONENAND_CMD_LOCK); 1280 + } 1281 + 1282 + /** 1283 + * onenand_unlock - [MTD Interface] Unlock block(s) 1284 + * @param mtd MTD device structure 1285 + * @param ofs offset relative to mtd start 1286 + * @param len number of bytes to unlock 1287 + * 1288 + * Unlock one or more blocks 1289 + */ 1290 + static int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len) 1291 + { 1292 + return onenand_do_lock_cmd(mtd, ofs, len, ONENAND_CMD_UNLOCK); 1293 } 1294 1295 /** ··· 1310 this->command(mtd, ONENAND_CMD_UNLOCK_ALL, 0, 0); 1311 1312 /* There's no return value */ 1313 + this->wait(mtd, FL_LOCKING); 1314 1315 /* Sanity check */ 1316 while (this->read_word(this->base + ONENAND_REG_CTRL_STATUS) ··· 1334 return 0; 1335 } 1336 1337 + onenand_unlock(mtd, 0x0, this->chipsize); 1338 1339 return 0; 1340 } ··· 1762 /* Read manufacturer and device IDs from Register */ 1763 maf_id = this->read_word(this->base + ONENAND_REG_MANUFACTURER_ID); 1764 dev_id = this->read_word(this->base + ONENAND_REG_DEVICE_ID); 1765 + ver_id = this->read_word(this->base + ONENAND_REG_VERSION_ID); 1766 1767 /* Check OneNAND device */ 1768 if (maf_id != bram_maf_id || dev_id != bram_dev_id) ··· 1846 if (!this->command) 1847 this->command = onenand_command; 1848 if (!this->wait) 1849 + onenand_setup_wait(mtd); 1850 1851 if (!this->read_bufferram) 1852 this->read_bufferram = onenand_read_bufferram; ··· 1883 init_waitqueue_head(&this->wq); 1884 spin_lock_init(&this->chip_lock); 1885 1886 + /* 1887 + * Allow subpage writes up to oobsize. 1888 + */ 1889 switch (mtd->oobsize) { 1890 case 64: 1891 this->ecclayout = &onenand_oob_64; 1892 + mtd->subpage_sft = 2; 1893 break; 1894 1895 case 32: 1896 this->ecclayout = &onenand_oob_32; 1897 + mtd->subpage_sft = 1; 1898 break; 1899 1900 default: 1901 printk(KERN_WARNING "No OOB scheme defined for oobsize %d\n", 1902 mtd->oobsize); 1903 + mtd->subpage_sft = 0; 1904 /* To prevent kernel oops */ 1905 this->ecclayout = &onenand_oob_32; 1906 break; 1907 } 1908 1909 + this->subpagesize = mtd->writesize >> mtd->subpage_sft; 1910 mtd->ecclayout = this->ecclayout; 1911 1912 /* Fill in remaining MTD driver data */ ··· 1922 mtd->lock_user_prot_reg = onenand_lock_user_prot_reg; 1923 #endif 1924 mtd->sync = onenand_sync; 1925 + mtd->lock = onenand_lock; 1926 mtd->unlock = onenand_unlock; 1927 mtd->suspend = onenand_suspend; 1928 mtd->resume = onenand_resume;
+6 -8
drivers/mtd/onenand/onenand_bbt.c
··· 93 ret = onenand_do_read_oob(mtd, from + j * mtd->writesize + bd->offs, 94 readlen, &retlen, &buf[0]); 95 96 - if (ret) 97 return ret; 98 99 if (check_short_pattern(&buf[j * scanlen], scanlen, mtd->writesize, bd)) { 100 bbm->bbt[i >> 3] |= 0x03 << (i & 0x6); 101 printk(KERN_WARNING "Bad eraseblock %d at 0x%08x\n", 102 i >> 1, (unsigned int) from); 103 break; 104 } 105 } ··· 179 int len, ret = 0; 180 181 len = mtd->size >> (this->erase_shift + 2); 182 - /* Allocate memory (2bit per block) */ 183 - bbm->bbt = kmalloc(len, GFP_KERNEL); 184 if (!bbm->bbt) { 185 printk(KERN_ERR "onenand_scan_bbt: Out of memory\n"); 186 return -ENOMEM; 187 } 188 - /* Clear the memory bad block table */ 189 - memset(bbm->bbt, 0x00, len); 190 191 /* Set the bad block position */ 192 bbm->badblockpos = ONENAND_BADBLOCK_POS; ··· 230 struct onenand_chip *this = mtd->priv; 231 struct bbm_info *bbm; 232 233 - this->bbm = kmalloc(sizeof(struct bbm_info), GFP_KERNEL); 234 if (!this->bbm) 235 return -ENOMEM; 236 237 bbm = this->bbm; 238 - 239 - memset(bbm, 0, sizeof(struct bbm_info)); 240 241 /* 1KB page has same configuration as 2KB page */ 242 if (!bbm->badblock_pattern)
··· 93 ret = onenand_do_read_oob(mtd, from + j * mtd->writesize + bd->offs, 94 readlen, &retlen, &buf[0]); 95 96 + /* If it is a initial bad block, just ignore it */ 97 + if (ret && !(ret & ONENAND_CTRL_LOAD)) 98 return ret; 99 100 if (check_short_pattern(&buf[j * scanlen], scanlen, mtd->writesize, bd)) { 101 bbm->bbt[i >> 3] |= 0x03 << (i & 0x6); 102 printk(KERN_WARNING "Bad eraseblock %d at 0x%08x\n", 103 i >> 1, (unsigned int) from); 104 + mtd->ecc_stats.badblocks++; 105 break; 106 } 107 } ··· 177 int len, ret = 0; 178 179 len = mtd->size >> (this->erase_shift + 2); 180 + /* Allocate memory (2bit per block) and clear the memory bad block table */ 181 + bbm->bbt = kzalloc(len, GFP_KERNEL); 182 if (!bbm->bbt) { 183 printk(KERN_ERR "onenand_scan_bbt: Out of memory\n"); 184 return -ENOMEM; 185 } 186 187 /* Set the bad block position */ 188 bbm->badblockpos = ONENAND_BADBLOCK_POS; ··· 230 struct onenand_chip *this = mtd->priv; 231 struct bbm_info *bbm; 232 233 + this->bbm = kzalloc(sizeof(struct bbm_info), GFP_KERNEL); 234 if (!this->bbm) 235 return -ENOMEM; 236 237 bbm = this->bbm; 238 239 /* 1KB page has same configuration as 2KB page */ 240 if (!bbm->badblock_pattern)
+24 -6
drivers/mtd/redboot.c
··· 96 */ 97 if (swab32(buf[i].size) == master->erasesize) { 98 int j; 99 - for (j = 0; j < numslots && buf[j].name[0] != 0xff; ++j) { 100 /* The unsigned long fields were written with the 101 * wrong byte sex, name and pad have no byte sex. 102 */ ··· 122 } 123 } 124 break; 125 } 126 } 127 if (i == numslots) { ··· 138 for (i = 0; i < numslots; i++) { 139 struct fis_list *new_fl, **prev; 140 141 - if (buf[i].name[0] == 0xff) 142 - continue; 143 if (!redboot_checksum(&buf[i])) 144 break; 145 ··· 185 } 186 } 187 #endif 188 - parts = kmalloc(sizeof(*parts)*nrparts + nulllen + namelen, GFP_KERNEL); 189 190 if (!parts) { 191 ret = -ENOMEM; 192 goto out; 193 } 194 - 195 - memset(parts, 0, sizeof(*parts)*nrparts + nulllen + namelen); 196 197 nullname = (char *)&parts[nrparts]; 198 #ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED
··· 96 */ 97 if (swab32(buf[i].size) == master->erasesize) { 98 int j; 99 + for (j = 0; j < numslots; ++j) { 100 + 101 + /* A single 0xff denotes a deleted entry. 102 + * Two of them in a row is the end of the table. 103 + */ 104 + if (buf[j].name[0] == 0xff) { 105 + if (buf[j].name[1] == 0xff) { 106 + break; 107 + } else { 108 + continue; 109 + } 110 + } 111 + 112 /* The unsigned long fields were written with the 113 * wrong byte sex, name and pad have no byte sex. 114 */ ··· 110 } 111 } 112 break; 113 + } else { 114 + /* re-calculate of real numslots */ 115 + numslots = buf[i].size / sizeof(struct fis_image_desc); 116 } 117 } 118 if (i == numslots) { ··· 123 for (i = 0; i < numslots; i++) { 124 struct fis_list *new_fl, **prev; 125 126 + if (buf[i].name[0] == 0xff) { 127 + if (buf[i].name[1] == 0xff) { 128 + break; 129 + } else { 130 + continue; 131 + } 132 + } 133 if (!redboot_checksum(&buf[i])) 134 break; 135 ··· 165 } 166 } 167 #endif 168 + parts = kzalloc(sizeof(*parts)*nrparts + nulllen + namelen, GFP_KERNEL); 169 170 if (!parts) { 171 ret = -ENOMEM; 172 goto out; 173 } 174 175 nullname = (char *)&parts[nrparts]; 176 #ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED
+2 -1
drivers/mtd/rfd_ftl.c
··· 787 788 if (scan_header(part) == 0) { 789 part->mbd.size = part->sector_count; 790 - part->mbd.blksize = SECTOR_SIZE; 791 part->mbd.tr = tr; 792 part->mbd.devnum = -1; 793 if (!(mtd->flags & MTD_WRITEABLE)) ··· 828 .name = "rfd", 829 .major = RFD_FTL_MAJOR, 830 .part_bits = PART_BITS, 831 .readsect = rfd_ftl_readsect, 832 .writesect = rfd_ftl_writesect, 833 .getgeo = rfd_ftl_getgeo,
··· 787 788 if (scan_header(part) == 0) { 789 part->mbd.size = part->sector_count; 790 part->mbd.tr = tr; 791 part->mbd.devnum = -1; 792 if (!(mtd->flags & MTD_WRITEABLE)) ··· 829 .name = "rfd", 830 .major = RFD_FTL_MAJOR, 831 .part_bits = PART_BITS, 832 + .blksize = SECTOR_SIZE, 833 + 834 .readsect = rfd_ftl_readsect, 835 .writesect = rfd_ftl_writesect, 836 .getgeo = rfd_ftl_getgeo,
+3 -4
drivers/mtd/ssfdc.c
··· 172 173 ops.mode = MTD_OOB_RAW; 174 ops.ooboffs = 0; 175 - ops.ooblen = mtd->oobsize; 176 - ops.len = OOB_SIZE; 177 ops.oobbuf = buf; 178 ops.datbuf = NULL; 179 180 ret = mtd->read_oob(mtd, offs, &ops); 181 - if (ret < 0 || ops.retlen != OOB_SIZE) 182 return -1; 183 184 return 0; ··· 311 312 ssfdc->mbd.mtd = mtd; 313 ssfdc->mbd.devnum = -1; 314 - ssfdc->mbd.blksize = SECTOR_SIZE; 315 ssfdc->mbd.tr = tr; 316 ssfdc->mbd.readonly = 1; 317 ··· 445 .name = "ssfdc", 446 .major = SSFDCR_MAJOR, 447 .part_bits = SSFDCR_PARTN_BITS, 448 .getgeo = ssfdcr_getgeo, 449 .readsect = ssfdcr_readsect, 450 .add_mtd = ssfdcr_add_mtd,
··· 172 173 ops.mode = MTD_OOB_RAW; 174 ops.ooboffs = 0; 175 + ops.ooblen = OOB_SIZE; 176 ops.oobbuf = buf; 177 ops.datbuf = NULL; 178 179 ret = mtd->read_oob(mtd, offs, &ops); 180 + if (ret < 0 || ops.oobretlen != OOB_SIZE) 181 return -1; 182 183 return 0; ··· 312 313 ssfdc->mbd.mtd = mtd; 314 ssfdc->mbd.devnum = -1; 315 ssfdc->mbd.tr = tr; 316 ssfdc->mbd.readonly = 1; 317 ··· 447 .name = "ssfdc", 448 .major = SSFDCR_MAJOR, 449 .part_bits = SSFDCR_PARTN_BITS, 450 + .blksize = SECTOR_SIZE, 451 .getgeo = ssfdcr_getgeo, 452 .readsect = ssfdcr_readsect, 453 .add_mtd = ssfdcr_add_mtd,
+2 -1
fs/jffs/jffs_fm.c
··· 17 * 18 */ 19 #include <linux/slab.h> 20 #include <linux/blkdev.h> 21 #include <linux/jffs.h> 22 #include "jffs_fm.h" ··· 105 106 mtd = get_mtd_device(NULL, unit); 107 108 - if (!mtd) { 109 kfree(fmc); 110 DJM(no_jffs_fmcontrol--); 111 return NULL;
··· 17 * 18 */ 19 #include <linux/slab.h> 20 + #include <linux/err.h> 21 #include <linux/blkdev.h> 22 #include <linux/jffs.h> 23 #include "jffs_fm.h" ··· 104 105 mtd = get_mtd_device(NULL, unit); 106 107 + if (IS_ERR(mtd)) { 108 kfree(fmc); 109 DJM(no_jffs_fmcontrol--); 110 return NULL;
+2 -2
fs/jffs2/debug.c
··· 178 while (ref2) { 179 uint32_t totlen = ref_totlen(c, jeb, ref2); 180 181 - if (ref2->flash_offset < jeb->offset || 182 - ref2->flash_offset > jeb->offset + c->sector_size) { 183 JFFS2_ERROR("node_ref %#08x shouldn't be in block at %#08x.\n", 184 ref_offset(ref2), jeb->offset); 185 goto error;
··· 178 while (ref2) { 179 uint32_t totlen = ref_totlen(c, jeb, ref2); 180 181 + if (ref_offset(ref2) < jeb->offset || 182 + ref_offset(ref2) > jeb->offset + c->sector_size) { 183 JFFS2_ERROR("node_ref %#08x shouldn't be in block at %#08x.\n", 184 ref_offset(ref2), jeb->offset); 185 goto error;
+1
fs/jffs2/debug.h
··· 13 #ifndef _JFFS2_DEBUG_H_ 14 #define _JFFS2_DEBUG_H_ 15 16 17 #ifndef CONFIG_JFFS2_FS_DEBUG 18 #define CONFIG_JFFS2_FS_DEBUG 0
··· 13 #ifndef _JFFS2_DEBUG_H_ 14 #define _JFFS2_DEBUG_H_ 15 16 + #include <linux/sched.h> 17 18 #ifndef CONFIG_JFFS2_FS_DEBUG 19 #define CONFIG_JFFS2_FS_DEBUG 0
+1 -2
fs/jffs2/fs.c
··· 502 if (ret) 503 return ret; 504 505 - c->inocache_list = kmalloc(INOCACHE_HASHSIZE * sizeof(struct jffs2_inode_cache *), GFP_KERNEL); 506 if (!c->inocache_list) { 507 ret = -ENOMEM; 508 goto out_wbuf; 509 } 510 - memset(c->inocache_list, 0, INOCACHE_HASHSIZE * sizeof(struct jffs2_inode_cache *)); 511 512 jffs2_init_xattr_subsystem(c); 513
··· 502 if (ret) 503 return ret; 504 505 + c->inocache_list = kcalloc(INOCACHE_HASHSIZE, sizeof(struct jffs2_inode_cache *), GFP_KERNEL); 506 if (!c->inocache_list) { 507 ret = -ENOMEM; 508 goto out_wbuf; 509 } 510 511 jffs2_init_xattr_subsystem(c); 512
+2
fs/jffs2/gc.c
··· 838 839 for (raw = f->inocache->nodes; raw != (void *)f->inocache; raw = raw->next_in_ino) { 840 841 /* We only care about obsolete ones */ 842 if (!(ref_obsolete(raw))) 843 continue;
··· 838 839 for (raw = f->inocache->nodes; raw != (void *)f->inocache; raw = raw->next_in_ino) { 840 841 + cond_resched(); 842 + 843 /* We only care about obsolete ones */ 844 if (!(ref_obsolete(raw))) 845 continue;
+4 -6
fs/jffs2/nodelist.h
··· 294 295 static inline struct jffs2_node_frag *frag_first(struct rb_root *root) 296 { 297 - struct rb_node *node = root->rb_node; 298 299 if (!node) 300 return NULL; 301 - while(node->rb_left) 302 - node = node->rb_left; 303 return rb_entry(node, struct jffs2_node_frag, rb); 304 } 305 306 static inline struct jffs2_node_frag *frag_last(struct rb_root *root) 307 { 308 - struct rb_node *node = root->rb_node; 309 310 if (!node) 311 return NULL; 312 - while(node->rb_right) 313 - node = node->rb_right; 314 return rb_entry(node, struct jffs2_node_frag, rb); 315 } 316
··· 294 295 static inline struct jffs2_node_frag *frag_first(struct rb_root *root) 296 { 297 + struct rb_node *node = rb_first(root); 298 299 if (!node) 300 return NULL; 301 + 302 return rb_entry(node, struct jffs2_node_frag, rb); 303 } 304 305 static inline struct jffs2_node_frag *frag_last(struct rb_root *root) 306 { 307 + struct rb_node *node = rb_last(root); 308 309 if (!node) 310 return NULL; 311 + 312 return rb_entry(node, struct jffs2_node_frag, rb); 313 } 314
+1 -2
fs/jffs2/readinode.c
··· 944 int jffs2_do_crccheck_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic) 945 { 946 struct jffs2_raw_inode n; 947 - struct jffs2_inode_info *f = kmalloc(sizeof(*f), GFP_KERNEL); 948 int ret; 949 950 if (!f) 951 return -ENOMEM; 952 953 - memset(f, 0, sizeof(*f)); 954 init_MUTEX_LOCKED(&f->sem); 955 f->inocache = ic; 956
··· 944 int jffs2_do_crccheck_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic) 945 { 946 struct jffs2_raw_inode n; 947 + struct jffs2_inode_info *f = kzalloc(sizeof(*f), GFP_KERNEL); 948 int ret; 949 950 if (!f) 951 return -ENOMEM; 952 953 init_MUTEX_LOCKED(&f->sem); 954 f->inocache = ic; 955
+4 -2
fs/jffs2/scan.c
··· 128 } 129 130 if (jffs2_sum_active()) { 131 - s = kmalloc(sizeof(struct jffs2_summary), GFP_KERNEL); 132 if (!s) { 133 JFFS2_WARNING("Can't allocate memory for summary\n"); 134 return -ENOMEM; 135 } 136 - memset(s, 0, sizeof(struct jffs2_summary)); 137 } 138 139 for (i=0; i<c->nr_blocks; i++) { 140 struct jffs2_eraseblock *jeb = &c->blocks[i]; 141 142 /* reset summary info for next eraseblock scan */ 143 jffs2_sum_reset_collected(s);
··· 128 } 129 130 if (jffs2_sum_active()) { 131 + s = kzalloc(sizeof(struct jffs2_summary), GFP_KERNEL); 132 if (!s) { 133 + kfree(flashbuf); 134 JFFS2_WARNING("Can't allocate memory for summary\n"); 135 return -ENOMEM; 136 } 137 } 138 139 for (i=0; i<c->nr_blocks; i++) { 140 struct jffs2_eraseblock *jeb = &c->blocks[i]; 141 + 142 + cond_resched(); 143 144 /* reset summary info for next eraseblock scan */ 145 jffs2_sum_reset_collected(s);
+3 -3
fs/jffs2/summary.c
··· 26 27 int jffs2_sum_init(struct jffs2_sb_info *c) 28 { 29 - c->summary = kmalloc(sizeof(struct jffs2_summary), GFP_KERNEL); 30 31 if (!c->summary) { 32 JFFS2_WARNING("Can't allocate memory for summary information!\n"); 33 return -ENOMEM; 34 } 35 - 36 - memset(c->summary, 0, sizeof(struct jffs2_summary)); 37 38 c->summary->sum_buf = vmalloc(c->sector_size); 39 ··· 395 396 for (i=0; i<je32_to_cpu(summary->sum_num); i++) { 397 dbg_summary("processing summary index %d\n", i); 398 399 /* Make sure there's a spare ref for dirty space */ 400 err = jffs2_prealloc_raw_node_refs(c, jeb, 2);
··· 26 27 int jffs2_sum_init(struct jffs2_sb_info *c) 28 { 29 + c->summary = kzalloc(sizeof(struct jffs2_summary), GFP_KERNEL); 30 31 if (!c->summary) { 32 JFFS2_WARNING("Can't allocate memory for summary information!\n"); 33 return -ENOMEM; 34 } 35 36 c->summary->sum_buf = vmalloc(c->sector_size); 37 ··· 397 398 for (i=0; i<je32_to_cpu(summary->sum_num); i++) { 399 dbg_summary("processing summary index %d\n", i); 400 + 401 + cond_resched(); 402 403 /* Make sure there's a spare ref for dirty space */ 404 err = jffs2_prealloc_raw_node_refs(c, jeb, 2);
+4 -3
fs/jffs2/super.c
··· 17 #include <linux/init.h> 18 #include <linux/list.h> 19 #include <linux/fs.h> 20 #include <linux/mount.h> 21 #include <linux/jffs2.h> 22 #include <linux/pagemap.h> ··· 185 struct mtd_info *mtd; 186 187 mtd = get_mtd_device(NULL, mtdnr); 188 - if (!mtd) { 189 D1(printk(KERN_DEBUG "jffs2: MTD device #%u doesn't appear to exist\n", mtdnr)); 190 - return -EINVAL; 191 } 192 193 return jffs2_get_sb_mtd(fs_type, flags, dev_name, data, mtd, mnt); ··· 222 D1(printk(KERN_DEBUG "jffs2_get_sb(): mtd:%%s, name \"%s\"\n", dev_name+4)); 223 for (mtdnr = 0; mtdnr < MAX_MTD_DEVICES; mtdnr++) { 224 mtd = get_mtd_device(NULL, mtdnr); 225 - if (mtd) { 226 if (!strcmp(mtd->name, dev_name+4)) 227 return jffs2_get_sb_mtd(fs_type, flags, dev_name, data, mtd, mnt); 228 put_mtd_device(mtd);
··· 17 #include <linux/init.h> 18 #include <linux/list.h> 19 #include <linux/fs.h> 20 + #include <linux/err.h> 21 #include <linux/mount.h> 22 #include <linux/jffs2.h> 23 #include <linux/pagemap.h> ··· 184 struct mtd_info *mtd; 185 186 mtd = get_mtd_device(NULL, mtdnr); 187 + if (IS_ERR(mtd)) { 188 D1(printk(KERN_DEBUG "jffs2: MTD device #%u doesn't appear to exist\n", mtdnr)); 189 + return PTR_ERR(mtd); 190 } 191 192 return jffs2_get_sb_mtd(fs_type, flags, dev_name, data, mtd, mnt); ··· 221 D1(printk(KERN_DEBUG "jffs2_get_sb(): mtd:%%s, name \"%s\"\n", dev_name+4)); 222 for (mtdnr = 0; mtdnr < MAX_MTD_DEVICES; mtdnr++) { 223 mtd = get_mtd_device(NULL, mtdnr); 224 + if (!IS_ERR(mtd)) { 225 if (!strcmp(mtd->name, dev_name+4)) 226 return jffs2_get_sb_mtd(fs_type, flags, dev_name, data, mtd, mnt); 227 put_mtd_device(mtd);
+1 -1
fs/jffs2/symlink.c
··· 51 */ 52 53 if (!p) { 54 - printk(KERN_ERR "jffs2_follow_link(): can't find symlink taerget\n"); 55 p = ERR_PTR(-EIO); 56 } 57 D1(printk(KERN_DEBUG "jffs2_follow_link(): target path is '%s'\n", (char *) f->target));
··· 51 */ 52 53 if (!p) { 54 + printk(KERN_ERR "jffs2_follow_link(): can't find symlink target\n"); 55 p = ERR_PTR(-EIO); 56 } 57 D1(printk(KERN_DEBUG "jffs2_follow_link(): target path is '%s'\n", (char *) f->target));
+9 -12
fs/jffs2/wbuf.c
··· 969 int oobsize = c->mtd->oobsize; 970 struct mtd_oob_ops ops; 971 972 - ops.len = NR_OOB_SCAN_PAGES * oobsize; 973 - ops.ooblen = oobsize; 974 ops.oobbuf = c->oobbuf; 975 ops.ooboffs = 0; 976 ops.datbuf = NULL; ··· 982 return ret; 983 } 984 985 - if (ops.retlen < ops.len) { 986 D1(printk(KERN_WARNING "jffs2_check_oob_empty(): Read OOB " 987 "returned short read (%zd bytes not %d) for block " 988 - "at %08x\n", ops.retlen, ops.len, jeb->offset)); 989 return -EIO; 990 } 991 ··· 1004 } 1005 1006 /* we know, we are aligned :) */ 1007 - for (page = oobsize; page < ops.len; page += sizeof(long)) { 1008 long dat = *(long *)(&ops.oobbuf[page]); 1009 if(dat != -1) 1010 return 1; ··· 1032 return 2; 1033 } 1034 1035 - ops.len = oobsize; 1036 ops.ooblen = oobsize; 1037 ops.oobbuf = c->oobbuf; 1038 ops.ooboffs = 0; ··· 1046 return ret; 1047 } 1048 1049 - if (ops.retlen < ops.len) { 1050 D1 (printk (KERN_WARNING "jffs2_check_nand_cleanmarker(): " 1051 "Read OOB return short read (%zd bytes not %d) " 1052 - "for block at %08x\n", ops.retlen, ops.len, 1053 jeb->offset)); 1054 return -EIO; 1055 } ··· 1088 n.nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER); 1089 n.totlen = cpu_to_je32(8); 1090 1091 - ops.len = c->fsdata_len; 1092 - ops.ooblen = c->fsdata_len;; 1093 ops.oobbuf = (uint8_t *)&n; 1094 ops.ooboffs = c->fsdata_pos; 1095 ops.datbuf = NULL; ··· 1102 jeb->offset, ret)); 1103 return ret; 1104 } 1105 - if (ops.retlen != ops.len) { 1106 D1(printk(KERN_WARNING "jffs2_write_nand_cleanmarker(): " 1107 "Short write for block at %08x: %zd not %d\n", 1108 - jeb->offset, ops.retlen, ops.len)); 1109 return -EIO; 1110 } 1111 return 0;
··· 969 int oobsize = c->mtd->oobsize; 970 struct mtd_oob_ops ops; 971 972 + ops.ooblen = NR_OOB_SCAN_PAGES * oobsize; 973 ops.oobbuf = c->oobbuf; 974 ops.ooboffs = 0; 975 ops.datbuf = NULL; ··· 983 return ret; 984 } 985 986 + if (ops.oobretlen < ops.ooblen) { 987 D1(printk(KERN_WARNING "jffs2_check_oob_empty(): Read OOB " 988 "returned short read (%zd bytes not %d) for block " 989 + "at %08x\n", ops.oobretlen, ops.ooblen, jeb->offset)); 990 return -EIO; 991 } 992 ··· 1005 } 1006 1007 /* we know, we are aligned :) */ 1008 + for (page = oobsize; page < ops.ooblen; page += sizeof(long)) { 1009 long dat = *(long *)(&ops.oobbuf[page]); 1010 if(dat != -1) 1011 return 1; ··· 1033 return 2; 1034 } 1035 1036 ops.ooblen = oobsize; 1037 ops.oobbuf = c->oobbuf; 1038 ops.ooboffs = 0; ··· 1048 return ret; 1049 } 1050 1051 + if (ops.oobretlen < ops.ooblen) { 1052 D1 (printk (KERN_WARNING "jffs2_check_nand_cleanmarker(): " 1053 "Read OOB return short read (%zd bytes not %d) " 1054 + "for block at %08x\n", ops.oobretlen, ops.ooblen, 1055 jeb->offset)); 1056 return -EIO; 1057 } ··· 1090 n.nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER); 1091 n.totlen = cpu_to_je32(8); 1092 1093 + ops.ooblen = c->fsdata_len; 1094 ops.oobbuf = (uint8_t *)&n; 1095 ops.ooboffs = c->fsdata_pos; 1096 ops.datbuf = NULL; ··· 1105 jeb->offset, ret)); 1106 return ret; 1107 } 1108 + if (ops.oobretlen != ops.ooblen) { 1109 D1(printk(KERN_WARNING "jffs2_write_nand_cleanmarker(): " 1110 "Short write for block at %08x: %zd not %d\n", 1111 + jeb->offset, ops.oobretlen, ops.ooblen)); 1112 return -EIO; 1113 } 1114 return 0;
+2 -3
fs/jffs2/xattr.c
··· 399 { 400 /* must be called under down_write(xattr_sem) */ 401 if (atomic_dec_and_lock(&xd->refcnt, &c->erase_completion_lock)) { 402 - uint32_t xid = xd->xid, version = xd->version; 403 - 404 unload_xattr_datum(c, xd); 405 xd->flags |= JFFS2_XFLAGS_DEAD; 406 if (xd->node == (void *)xd) { ··· 409 } 410 spin_unlock(&c->erase_completion_lock); 411 412 - dbg_xattr("xdatum(xid=%u, version=%u) was removed.\n", xid, version); 413 } 414 } 415
··· 399 { 400 /* must be called under down_write(xattr_sem) */ 401 if (atomic_dec_and_lock(&xd->refcnt, &c->erase_completion_lock)) { 402 unload_xattr_datum(c, xd); 403 xd->flags |= JFFS2_XFLAGS_DEAD; 404 if (xd->node == (void *)xd) { ··· 411 } 412 spin_unlock(&c->erase_completion_lock); 413 414 + dbg_xattr("xdatum(xid=%u, version=%u) was removed.\n", 415 + xd->xid, xd->version); 416 } 417 } 418
+2 -1
include/linux/mtd/blktrans.h
··· 24 struct mtd_info *mtd; 25 struct mutex lock; 26 int devnum; 27 - int blksize; 28 unsigned long size; 29 int readonly; 30 void *blkcore_priv; /* gendisk in 2.5, devfs_handle in 2.4 */ ··· 35 char *name; 36 int major; 37 int part_bits; 38 39 /* Access functions */ 40 int (*readsect)(struct mtd_blktrans_dev *dev,
··· 24 struct mtd_info *mtd; 25 struct mutex lock; 26 int devnum; 27 unsigned long size; 28 int readonly; 29 void *blkcore_priv; /* gendisk in 2.5, devfs_handle in 2.4 */ ··· 36 char *name; 37 int major; 38 int part_bits; 39 + int blksize; 40 + int blkshift; 41 42 /* Access functions */ 43 int (*readsect)(struct mtd_blktrans_dev *dev,
+16 -8
include/linux/mtd/mtd.h
··· 23 24 #define MTD_CHAR_MAJOR 90 25 #define MTD_BLOCK_MAJOR 31 26 - #define MAX_MTD_DEVICES 16 27 28 #define MTD_ERASE_PENDING 0x01 29 #define MTD_ERASING 0x02 ··· 75 * struct mtd_oob_ops - oob operation operands 76 * @mode: operation mode 77 * 78 - * @len: number of bytes to write/read. When a data buffer is given 79 - * (datbuf != NULL) this is the number of data bytes. When 80 - * no data buffer is available this is the number of oob bytes. 81 * 82 - * @retlen: number of bytes written/read. When a data buffer is given 83 - * (datbuf != NULL) this is the number of data bytes. When 84 - * no data buffer is available this is the number of oob bytes. 85 * 86 - * @ooblen: number of oob bytes per page 87 * @ooboffs: offset of oob data in the oob area (only relevant when 88 * mode = MTD_OOB_PLACE) 89 * @datbuf: data buffer - if NULL only oob data are read/written ··· 91 size_t len; 92 size_t retlen; 93 size_t ooblen; 94 uint32_t ooboffs; 95 uint8_t *datbuf; 96 uint8_t *oobbuf; ··· 200 201 /* ECC status information */ 202 struct mtd_ecc_stats ecc_stats; 203 204 void *priv; 205 206 struct module *owner; 207 int usecount; 208 }; 209 210 ··· 223 extern int del_mtd_device (struct mtd_info *mtd); 224 225 extern struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num); 226 227 extern void put_mtd_device(struct mtd_info *mtd); 228
··· 23 24 #define MTD_CHAR_MAJOR 90 25 #define MTD_BLOCK_MAJOR 31 26 + #define MAX_MTD_DEVICES 32 27 28 #define MTD_ERASE_PENDING 0x01 29 #define MTD_ERASING 0x02 ··· 75 * struct mtd_oob_ops - oob operation operands 76 * @mode: operation mode 77 * 78 + * @len: number of data bytes to write/read 79 * 80 + * @retlen: number of data bytes written/read 81 * 82 + * @ooblen: number of oob bytes to write/read 83 + * @oobretlen: number of oob bytes written/read 84 * @ooboffs: offset of oob data in the oob area (only relevant when 85 * mode = MTD_OOB_PLACE) 86 * @datbuf: data buffer - if NULL only oob data are read/written ··· 94 size_t len; 95 size_t retlen; 96 size_t ooblen; 97 + size_t oobretlen; 98 uint32_t ooboffs; 99 uint8_t *datbuf; 100 uint8_t *oobbuf; ··· 202 203 /* ECC status information */ 204 struct mtd_ecc_stats ecc_stats; 205 + /* Subpage shift (NAND) */ 206 + int subpage_sft; 207 208 void *priv; 209 210 struct module *owner; 211 int usecount; 212 + 213 + /* If the driver is something smart, like UBI, it may need to maintain 214 + * its own reference counting. The below functions are only for driver. 215 + * The driver may register its callbacks. These callbacks are not 216 + * supposed to be called by MTD users */ 217 + int (*get_device) (struct mtd_info *mtd); 218 + void (*put_device) (struct mtd_info *mtd); 219 }; 220 221 ··· 216 extern int del_mtd_device (struct mtd_info *mtd); 217 218 extern struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num); 219 + extern struct mtd_info *get_mtd_device_nm(const char *name); 220 221 extern void put_mtd_device(struct mtd_info *mtd); 222
+10 -5
include/linux/mtd/nand.h
··· 166 * for all large page devices, as they do not support 167 * autoincrement.*/ 168 #define NAND_NO_READRDY 0x00000100 169 170 /* Options valid for Samsung large page devices */ 171 #define NAND_SAMSUNG_LP_OPTIONS \ ··· 196 /* Nand scan has allocated controller struct */ 197 #define NAND_CONTROLLER_ALLOC 0x80000000 198 199 200 /* 201 * nand_state_t - chip states ··· 292 * struct nand_buffers - buffer structure for read/write 293 * @ecccalc: buffer for calculated ecc 294 * @ecccode: buffer for ecc read from flash 295 - * @oobwbuf: buffer for write oob data 296 * @databuf: buffer for data - dynamically sized 297 - * @oobrbuf: buffer to read oob data 298 * 299 * Do not change the order of buffers. databuf and oobrbuf must be in 300 * consecutive order. ··· 300 struct nand_buffers { 301 uint8_t ecccalc[NAND_MAX_OOBSIZE]; 302 uint8_t ecccode[NAND_MAX_OOBSIZE]; 303 - uint8_t oobwbuf[NAND_MAX_OOBSIZE]; 304 - uint8_t databuf[NAND_MAX_PAGESIZE]; 305 - uint8_t oobrbuf[NAND_MAX_OOBSIZE]; 306 }; 307 308 /** ··· 347 * @chipsize: [INTERN] the size of one chip for multichip arrays 348 * @pagemask: [INTERN] page number mask = number of (pages / chip) - 1 349 * @pagebuf: [INTERN] holds the pagenumber which is currently in data_buf 350 * @ecclayout: [REPLACEABLE] the default ecc placement scheme 351 * @bbt: [INTERN] bad block table pointer 352 * @bbt_td: [REPLACEABLE] bad block table descriptor for flash lookup ··· 395 unsigned long chipsize; 396 int pagemask; 397 int pagebuf; 398 int badblockpos; 399 400 nand_state_t state;
··· 166 * for all large page devices, as they do not support 167 * autoincrement.*/ 168 #define NAND_NO_READRDY 0x00000100 169 + /* Chip does not allow subpage writes */ 170 + #define NAND_NO_SUBPAGE_WRITE 0x00000200 171 + 172 173 /* Options valid for Samsung large page devices */ 174 #define NAND_SAMSUNG_LP_OPTIONS \ ··· 193 /* Nand scan has allocated controller struct */ 194 #define NAND_CONTROLLER_ALLOC 0x80000000 195 196 + /* Cell info constants */ 197 + #define NAND_CI_CHIPNR_MSK 0x03 198 + #define NAND_CI_CELLTYPE_MSK 0x0C 199 200 /* 201 * nand_state_t - chip states ··· 286 * struct nand_buffers - buffer structure for read/write 287 * @ecccalc: buffer for calculated ecc 288 * @ecccode: buffer for ecc read from flash 289 * @databuf: buffer for data - dynamically sized 290 * 291 * Do not change the order of buffers. databuf and oobrbuf must be in 292 * consecutive order. ··· 296 struct nand_buffers { 297 uint8_t ecccalc[NAND_MAX_OOBSIZE]; 298 uint8_t ecccode[NAND_MAX_OOBSIZE]; 299 + uint8_t databuf[NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE]; 300 }; 301 302 /** ··· 345 * @chipsize: [INTERN] the size of one chip for multichip arrays 346 * @pagemask: [INTERN] page number mask = number of (pages / chip) - 1 347 * @pagebuf: [INTERN] holds the pagenumber which is currently in data_buf 348 + * @subpagesize: [INTERN] holds the subpagesize 349 * @ecclayout: [REPLACEABLE] the default ecc placement scheme 350 * @bbt: [INTERN] bad block table pointer 351 * @bbt_td: [REPLACEABLE] bad block table descriptor for flash lookup ··· 392 unsigned long chipsize; 393 int pagemask; 394 int pagebuf; 395 + int subpagesize; 396 + uint8_t cellinfo; 397 int badblockpos; 398 399 nand_state_t state;
+7 -1
include/linux/mtd/onenand.h
··· 13 #define __LINUX_MTD_ONENAND_H 14 15 #include <linux/spinlock.h> 16 #include <linux/mtd/onenand_regs.h> 17 #include <linux/mtd/bbm.h> 18 ··· 34 FL_WRITING, 35 FL_ERASING, 36 FL_SYNCING, 37 - FL_UNLOCKING, 38 FL_LOCKING, 39 FL_RESETING, 40 FL_OTPING, ··· 88 * operation is in progress 89 * @state: [INTERN] the current state of the OneNAND device 90 * @page_buf: data buffer 91 * @ecclayout: [REPLACEABLE] the default ecc placement scheme 92 * @bbm: [REPLACEABLE] pointer to Bad Block Management 93 * @priv: [OPTIONAL] pointer to private chip date ··· 121 int (*block_markbad)(struct mtd_info *mtd, loff_t ofs); 122 int (*scan_bbt)(struct mtd_info *mtd); 123 124 spinlock_t chip_lock; 125 wait_queue_head_t wq; 126 onenand_state_t state; 127 unsigned char *page_buf; 128 129 struct nand_ecclayout *ecclayout; 130 131 void *bbm; ··· 143 #define ONENAND_CURRENT_BUFFERRAM(this) (this->bufferram_index) 144 #define ONENAND_NEXT_BUFFERRAM(this) (this->bufferram_index ^ 1) 145 #define ONENAND_SET_NEXT_BUFFERRAM(this) (this->bufferram_index ^= 1) 146 147 #define ONENAND_GET_SYS_CFG1(this) \ 148 (this->read_word(this->base + ONENAND_REG_SYS_CFG1))
··· 13 #define __LINUX_MTD_ONENAND_H 14 15 #include <linux/spinlock.h> 16 + #include <linux/completion.h> 17 #include <linux/mtd/onenand_regs.h> 18 #include <linux/mtd/bbm.h> 19 ··· 33 FL_WRITING, 34 FL_ERASING, 35 FL_SYNCING, 36 FL_LOCKING, 37 FL_RESETING, 38 FL_OTPING, ··· 88 * operation is in progress 89 * @state: [INTERN] the current state of the OneNAND device 90 * @page_buf: data buffer 91 + * @subpagesize: [INTERN] holds the subpagesize 92 * @ecclayout: [REPLACEABLE] the default ecc placement scheme 93 * @bbm: [REPLACEABLE] pointer to Bad Block Management 94 * @priv: [OPTIONAL] pointer to private chip date ··· 120 int (*block_markbad)(struct mtd_info *mtd, loff_t ofs); 121 int (*scan_bbt)(struct mtd_info *mtd); 122 123 + struct completion complete; 124 + int irq; 125 + 126 spinlock_t chip_lock; 127 wait_queue_head_t wq; 128 onenand_state_t state; 129 unsigned char *page_buf; 130 131 + int subpagesize; 132 struct nand_ecclayout *ecclayout; 133 134 void *bbm; ··· 138 #define ONENAND_CURRENT_BUFFERRAM(this) (this->bufferram_index) 139 #define ONENAND_NEXT_BUFFERRAM(this) (this->bufferram_index ^ 1) 140 #define ONENAND_SET_NEXT_BUFFERRAM(this) (this->bufferram_index ^= 1) 141 + #define ONENAND_SET_PREV_BUFFERRAM(this) (this->bufferram_index ^= 1) 142 143 #define ONENAND_GET_SYS_CFG1(this) \ 144 (this->read_word(this->base + ONENAND_REG_SYS_CFG1))
+1
include/linux/mtd/onenand_regs.h
··· 179 * ECC Status Reigser FF00h (R) 180 */ 181 #define ONENAND_ECC_1BIT (1 << 0) 182 #define ONENAND_ECC_2BIT (1 << 1) 183 #define ONENAND_ECC_2BIT_ALL (0xAAAA) 184
··· 179 * ECC Status Reigser FF00h (R) 180 */ 181 #define ONENAND_ECC_1BIT (1 << 0) 182 + #define ONENAND_ECC_1BIT_ALL (0x5555) 183 #define ONENAND_ECC_2BIT (1 << 1) 184 #define ONENAND_ECC_2BIT_ALL (0xAAAA) 185