1/* 2 * Copyright �� 2009 - Maxim Levitsky 3 * Common routines & support for xD format 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation. 8 */ 9#include <linux/kernel.h> 10#include <linux/mtd/nand.h> 11#include "sm_common.h" 12 13static struct nand_ecclayout nand_oob_sm = { 14 .eccbytes = 6, 15 .eccpos = {8, 9, 10, 13, 14, 15}, 16 .oobfree = { 17 {.offset = 0 , .length = 4}, /* reserved */ 18 {.offset = 6 , .length = 2}, /* LBA1 */ 19 {.offset = 11, .length = 2} /* LBA2 */ 20 } 21}; 22 23/* NOTE: This layout is is not compatabable with SmartMedia, */ 24/* because the 256 byte devices have page depenent oob layout */ 25/* However it does preserve the bad block markers */ 26/* If you use smftl, it will bypass this and work correctly */ 27/* If you not, then you break SmartMedia compliance anyway */ 28 29static struct nand_ecclayout nand_oob_sm_small = { 30 .eccbytes = 3, 31 .eccpos = {0, 1, 2}, 32 .oobfree = { 33 {.offset = 3 , .length = 2}, /* reserved */ 34 {.offset = 6 , .length = 2}, /* LBA1 */ 35 } 36}; 37 38 39static int sm_block_markbad(struct mtd_info *mtd, loff_t ofs) 40{ 41 struct mtd_oob_ops ops; 42 struct sm_oob oob; 43 int ret, error = 0; 44 45 memset(&oob, -1, SM_OOB_SIZE); 46 oob.block_status = 0x0F; 47 48 /* As long as this function is called on erase block boundaries 49 it will work correctly for 256 byte nand */ 50 ops.mode = MTD_OOB_PLACE; 51 ops.ooboffs = 0; 52 ops.ooblen = mtd->oobsize; 53 ops.oobbuf = (void *)&oob; 54 ops.datbuf = NULL; 55 56 57 ret = mtd->write_oob(mtd, ofs, &ops); 58 if (ret < 0 || ops.oobretlen != SM_OOB_SIZE) { 59 printk(KERN_NOTICE 60 "sm_common: can't mark sector at %i as bad\n", 61 (int)ofs); 62 error = -EIO; 63 } else 64 mtd->ecc_stats.badblocks++; 65 66 return error; 67} 68 69 70static struct nand_flash_dev nand_smartmedia_flash_ids[] = { 71 {"SmartMedia 1MiB 5V", 0x6e, 256, 1, 0x1000, 0}, 72 {"SmartMedia 1MiB 3,3V", 0xe8, 256, 1, 0x1000, 0}, 73 {"SmartMedia 1MiB 3,3V", 0xec, 256, 1, 0x1000, 0}, 74 {"SmartMedia 2MiB 3,3V", 0xea, 256, 2, 0x1000, 0}, 75 {"SmartMedia 2MiB 5V", 0x64, 256, 2, 0x1000, 0}, 76 {"SmartMedia 2MiB 3,3V ROM", 0x5d, 512, 2, 0x2000, NAND_ROM}, 77 {"SmartMedia 4MiB 3,3V", 0xe3, 512, 4, 0x2000, 0}, 78 {"SmartMedia 4MiB 3,3/5V", 0xe5, 512, 4, 0x2000, 0}, 79 {"SmartMedia 4MiB 5V", 0x6b, 512, 4, 0x2000, 0}, 80 {"SmartMedia 4MiB 3,3V ROM", 0xd5, 512, 4, 0x2000, NAND_ROM}, 81 {"SmartMedia 8MiB 3,3V", 0xe6, 512, 8, 0x2000, 0}, 82 {"SmartMedia 8MiB 3,3V ROM", 0xd6, 512, 8, 0x2000, NAND_ROM}, 83 {"SmartMedia 16MiB 3,3V", 0x73, 512, 16, 0x4000, 0}, 84 {"SmartMedia 16MiB 3,3V ROM", 0x57, 512, 16, 0x4000, NAND_ROM}, 85 {"SmartMedia 32MiB 3,3V", 0x75, 512, 32, 0x4000, 0}, 86 {"SmartMedia 32MiB 3,3V ROM", 0x58, 512, 32, 0x4000, NAND_ROM}, 87 {"SmartMedia 64MiB 3,3V", 0x76, 512, 64, 0x4000, 0}, 88 {"SmartMedia 64MiB 3,3V ROM", 0xd9, 512, 64, 0x4000, NAND_ROM}, 89 {"SmartMedia 128MiB 3,3V", 0x79, 512, 128, 0x4000, 0}, 90 {"SmartMedia 128MiB 3,3V ROM", 0xda, 512, 128, 0x4000, NAND_ROM}, 91 {"SmartMedia 256MiB 3,3V", 0x71, 512, 256, 0x4000 }, 92 {"SmartMedia 256MiB 3,3V ROM", 0x5b, 512, 256, 0x4000, NAND_ROM}, 93 {NULL,} 94}; 95 96#define XD_TYPEM (NAND_NO_AUTOINCR | NAND_BROKEN_XD) 97static struct nand_flash_dev nand_xd_flash_ids[] = { 98 99 {"xD 16MiB 3,3V", 0x73, 512, 16, 0x4000, 0}, 100 {"xD 32MiB 3,3V", 0x75, 512, 32, 0x4000, 0}, 101 {"xD 64MiB 3,3V", 0x76, 512, 64, 0x4000, 0}, 102 {"xD 128MiB 3,3V", 0x79, 512, 128, 0x4000, 0}, 103 {"xD 256MiB 3,3V", 0x71, 512, 256, 0x4000, XD_TYPEM}, 104 {"xD 512MiB 3,3V", 0xdc, 512, 512, 0x4000, XD_TYPEM}, 105 {"xD 1GiB 3,3V", 0xd3, 512, 1024, 0x4000, XD_TYPEM}, 106 {"xD 2GiB 3,3V", 0xd5, 512, 2048, 0x4000, XD_TYPEM}, 107 {NULL,} 108}; 109 110int sm_register_device(struct mtd_info *mtd, int smartmedia) 111{ 112 struct nand_chip *chip = mtd->priv; 113 int ret; 114 115 chip->options |= NAND_SKIP_BBTSCAN; 116 117 /* Scan for card properties */ 118 ret = nand_scan_ident(mtd, 1, smartmedia ? 119 nand_smartmedia_flash_ids : nand_xd_flash_ids); 120 121 if (ret) 122 return ret; 123 124 /* Bad block marker postion */ 125 chip->badblockpos = 0x05; 126 chip->badblockbits = 7; 127 chip->block_markbad = sm_block_markbad; 128 129 /* ECC layout */ 130 if (mtd->writesize == SM_SECTOR_SIZE) 131 chip->ecc.layout = &nand_oob_sm; 132 else if (mtd->writesize == SM_SMALL_PAGE) 133 chip->ecc.layout = &nand_oob_sm_small; 134 else 135 return -ENODEV; 136 137 ret = nand_scan_tail(mtd); 138 139 if (ret) 140 return ret; 141 142 return add_mtd_device(mtd); 143} 144EXPORT_SYMBOL_GPL(sm_register_device); 145 146MODULE_LICENSE("GPL"); 147MODULE_AUTHOR("Maxim Levitsky <maximlevitsky@gmail.com>"); 148MODULE_DESCRIPTION("Common SmartMedia/xD functions"); 149