[go: nahoru, domu]

19fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky/*
29fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky * Copyright © 2009 - Maxim Levitsky
39fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky * Common routines & support for xD format
49fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky *
59fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky * This program is free software; you can redistribute it and/or modify
69fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky * it under the terms of the GNU General Public License version 2 as
79fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky * published by the Free Software Foundation.
89fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky */
99fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky#include <linux/kernel.h>
109fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky#include <linux/mtd/nand.h>
11a0e5cc581b3fc0e0a909e3cab48d9ec286c2a276Paul Gortmaker#include <linux/module.h>
120c4a235cb3c6464fd1886101fa9a1be933e340ddArtem Bityutskiy#include <linux/sizes.h>
139fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky#include "sm_common.h"
149fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky
159fc51a37a8da84618df7584cad67c078317f6720Maxim Levitskystatic struct nand_ecclayout nand_oob_sm = {
169fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky	.eccbytes = 6,
179fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky	.eccpos = {8, 9, 10, 13, 14, 15},
189fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky	.oobfree = {
199fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky		{.offset = 0 , .length = 4}, /* reserved */
209fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky		{.offset = 6 , .length = 2}, /* LBA1 */
219fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky		{.offset = 11, .length = 2}  /* LBA2 */
229fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky	}
239fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky};
249fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky
259fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky/* NOTE: This layout is is not compatabable with SmartMedia, */
269fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky/* because the 256 byte devices have page depenent oob layout */
279fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky/* However it does preserve the bad block markers */
289fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky/* If you use smftl, it will bypass this and work correctly */
299fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky/* If you not, then you break SmartMedia compliance anyway */
309fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky
319fc51a37a8da84618df7584cad67c078317f6720Maxim Levitskystatic struct nand_ecclayout nand_oob_sm_small = {
329fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky	.eccbytes = 3,
339fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky	.eccpos = {0, 1, 2},
349fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky	.oobfree = {
359fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky		{.offset = 3 , .length = 2}, /* reserved */
369fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky		{.offset = 6 , .length = 2}, /* LBA1 */
379fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky	}
389fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky};
399fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky
409fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky
419fc51a37a8da84618df7584cad67c078317f6720Maxim Levitskystatic int sm_block_markbad(struct mtd_info *mtd, loff_t ofs)
429fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky{
439fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky	struct mtd_oob_ops ops;
449fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky	struct sm_oob oob;
455a0edb251ae91c6f9b1f28dc165becd955666118Brian Norris	int ret;
469fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky
479fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky	memset(&oob, -1, SM_OOB_SIZE);
489fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky	oob.block_status = 0x0F;
499fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky
509fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky	/* As long as this function is called on erase block boundaries
519fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky		it will work correctly for 256 byte nand */
520612b9ddc2eeda014dd805c87c752b342d8f80f0Brian Norris	ops.mode = MTD_OPS_PLACE_OOB;
539fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky	ops.ooboffs = 0;
549fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky	ops.ooblen = mtd->oobsize;
559fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky	ops.oobbuf = (void *)&oob;
569fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky	ops.datbuf = NULL;
579fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky
589fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky
59a2cc5ba075f9bc837d0b4d4ec7328dcefc11859dArtem Bityutskiy	ret = mtd_write_oob(mtd, ofs, &ops);
609fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky	if (ret < 0 || ops.oobretlen != SM_OOB_SIZE) {
619fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky		printk(KERN_NOTICE
629fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky			"sm_common: can't mark sector at %i as bad\n",
639fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky								(int)ofs);
645a0edb251ae91c6f9b1f28dc165becd955666118Brian Norris		return -EIO;
655a0edb251ae91c6f9b1f28dc165becd955666118Brian Norris	}
669fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky
675a0edb251ae91c6f9b1f28dc165becd955666118Brian Norris	return 0;
689fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky}
699fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky
702764fb4244cc1bc08df3667924ca4a972e90ac70David Woodhousestatic struct nand_flash_dev nand_smartmedia_flash_ids[] = {
710c4a235cb3c6464fd1886101fa9a1be933e340ddArtem Bityutskiy	LEGACY_ID_NAND("SmartMedia 2MiB 3,3V ROM",   0x5d, 2,   SZ_8K, NAND_ROM),
720c4a235cb3c6464fd1886101fa9a1be933e340ddArtem Bityutskiy	LEGACY_ID_NAND("SmartMedia 4MiB 3,3V",       0xe3, 4,   SZ_8K, 0),
730c4a235cb3c6464fd1886101fa9a1be933e340ddArtem Bityutskiy	LEGACY_ID_NAND("SmartMedia 4MiB 3,3/5V",     0xe5, 4,   SZ_8K, 0),
740c4a235cb3c6464fd1886101fa9a1be933e340ddArtem Bityutskiy	LEGACY_ID_NAND("SmartMedia 4MiB 5V",         0x6b, 4,   SZ_8K, 0),
750c4a235cb3c6464fd1886101fa9a1be933e340ddArtem Bityutskiy	LEGACY_ID_NAND("SmartMedia 4MiB 3,3V ROM",   0xd5, 4,   SZ_8K, NAND_ROM),
760c4a235cb3c6464fd1886101fa9a1be933e340ddArtem Bityutskiy	LEGACY_ID_NAND("SmartMedia 8MiB 3,3V",       0xe6, 8,   SZ_8K, 0),
770c4a235cb3c6464fd1886101fa9a1be933e340ddArtem Bityutskiy	LEGACY_ID_NAND("SmartMedia 8MiB 3,3V ROM",   0xd6, 8,   SZ_8K, NAND_ROM),
780c4a235cb3c6464fd1886101fa9a1be933e340ddArtem Bityutskiy	LEGACY_ID_NAND("SmartMedia 16MiB 3,3V",      0x73, 16,  SZ_16K, 0),
790c4a235cb3c6464fd1886101fa9a1be933e340ddArtem Bityutskiy	LEGACY_ID_NAND("SmartMedia 16MiB 3,3V ROM",  0x57, 16,  SZ_16K, NAND_ROM),
800c4a235cb3c6464fd1886101fa9a1be933e340ddArtem Bityutskiy	LEGACY_ID_NAND("SmartMedia 32MiB 3,3V",      0x75, 32,  SZ_16K, 0),
810c4a235cb3c6464fd1886101fa9a1be933e340ddArtem Bityutskiy	LEGACY_ID_NAND("SmartMedia 32MiB 3,3V ROM",  0x58, 32,  SZ_16K, NAND_ROM),
820c4a235cb3c6464fd1886101fa9a1be933e340ddArtem Bityutskiy	LEGACY_ID_NAND("SmartMedia 64MiB 3,3V",      0x76, 64,  SZ_16K, 0),
830c4a235cb3c6464fd1886101fa9a1be933e340ddArtem Bityutskiy	LEGACY_ID_NAND("SmartMedia 64MiB 3,3V ROM",  0xd9, 64,  SZ_16K, NAND_ROM),
840c4a235cb3c6464fd1886101fa9a1be933e340ddArtem Bityutskiy	LEGACY_ID_NAND("SmartMedia 128MiB 3,3V",     0x79, 128, SZ_16K, 0),
850c4a235cb3c6464fd1886101fa9a1be933e340ddArtem Bityutskiy	LEGACY_ID_NAND("SmartMedia 128MiB 3,3V ROM", 0xda, 128, SZ_16K, NAND_ROM),
860c4a235cb3c6464fd1886101fa9a1be933e340ddArtem Bityutskiy	LEGACY_ID_NAND("SmartMedia 256MiB 3, 3V",    0x71, 256, SZ_16K, 0),
870c4a235cb3c6464fd1886101fa9a1be933e340ddArtem Bityutskiy	LEGACY_ID_NAND("SmartMedia 256MiB 3,3V ROM", 0x5b, 256, SZ_16K, NAND_ROM),
888dbfae1ef04311ba19d6b6c9a4d8fdddbb90ab0fArtem Bityutskiy	{NULL}
89c3611570ddf601609f8803574ea83889ff969aa0Maxim Levitsky};
902764fb4244cc1bc08df3667924ca4a972e90ac70David Woodhouse
91c3611570ddf601609f8803574ea83889ff969aa0Maxim Levitskystatic struct nand_flash_dev nand_xd_flash_ids[] = {
920c4a235cb3c6464fd1886101fa9a1be933e340ddArtem Bityutskiy	LEGACY_ID_NAND("xD 16MiB 3,3V",  0x73, 16,   SZ_16K, 0),
930c4a235cb3c6464fd1886101fa9a1be933e340ddArtem Bityutskiy	LEGACY_ID_NAND("xD 32MiB 3,3V",  0x75, 32,   SZ_16K, 0),
940c4a235cb3c6464fd1886101fa9a1be933e340ddArtem Bityutskiy	LEGACY_ID_NAND("xD 64MiB 3,3V",  0x76, 64,   SZ_16K, 0),
950c4a235cb3c6464fd1886101fa9a1be933e340ddArtem Bityutskiy	LEGACY_ID_NAND("xD 128MiB 3,3V", 0x79, 128,  SZ_16K, 0),
960c4a235cb3c6464fd1886101fa9a1be933e340ddArtem Bityutskiy	LEGACY_ID_NAND("xD 256MiB 3,3V", 0x71, 256,  SZ_16K, NAND_BROKEN_XD),
970c4a235cb3c6464fd1886101fa9a1be933e340ddArtem Bityutskiy	LEGACY_ID_NAND("xD 512MiB 3,3V", 0xdc, 512,  SZ_16K, NAND_BROKEN_XD),
980c4a235cb3c6464fd1886101fa9a1be933e340ddArtem Bityutskiy	LEGACY_ID_NAND("xD 1GiB 3,3V",   0xd3, 1024, SZ_16K, NAND_BROKEN_XD),
990c4a235cb3c6464fd1886101fa9a1be933e340ddArtem Bityutskiy	LEGACY_ID_NAND("xD 2GiB 3,3V",   0xd5, 2048, SZ_16K, NAND_BROKEN_XD),
1008dbfae1ef04311ba19d6b6c9a4d8fdddbb90ab0fArtem Bityutskiy	{NULL}
1012764fb4244cc1bc08df3667924ca4a972e90ac70David Woodhouse};
1022764fb4244cc1bc08df3667924ca4a972e90ac70David Woodhouse
103c3611570ddf601609f8803574ea83889ff969aa0Maxim Levitskyint sm_register_device(struct mtd_info *mtd, int smartmedia)
1049fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky{
105ece0ac98a13a555e6d46a02225fa15934abe7a3dKulikov Vasiliy	struct nand_chip *chip = mtd->priv;
1069fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky	int ret;
1079fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky
1082764fb4244cc1bc08df3667924ca4a972e90ac70David Woodhouse	chip->options |= NAND_SKIP_BBTSCAN;
1099fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky
1109fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky	/* Scan for card properties */
111c3611570ddf601609f8803574ea83889ff969aa0Maxim Levitsky	ret = nand_scan_ident(mtd, 1, smartmedia ?
112c3611570ddf601609f8803574ea83889ff969aa0Maxim Levitsky		nand_smartmedia_flash_ids : nand_xd_flash_ids);
1139fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky
1149fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky	if (ret)
1159fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky		return ret;
1169fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky
11725985edcedea6396277003854657b5f3cb31a628Lucas De Marchi	/* Bad block marker position */
1189fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky	chip->badblockpos = 0x05;
1199fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky	chip->badblockbits = 7;
1209fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky	chip->block_markbad = sm_block_markbad;
1219fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky
1229fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky	/* ECC layout */
1239fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky	if (mtd->writesize == SM_SECTOR_SIZE)
1249fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky		chip->ecc.layout = &nand_oob_sm;
1259fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky	else if (mtd->writesize == SM_SMALL_PAGE)
1269fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky		chip->ecc.layout = &nand_oob_sm_small;
1279fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky	else
1289fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky		return -ENODEV;
1299fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky
1309fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky	ret = nand_scan_tail(mtd);
1319fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky
1329fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky	if (ret)
1339fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky		return ret;
1349fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky
135ee0e87b174bb41f0310cf089262bf5dd8f95a212Jamie Iles	return mtd_device_register(mtd, NULL, 0);
1369fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky}
1379fc51a37a8da84618df7584cad67c078317f6720Maxim LevitskyEXPORT_SYMBOL_GPL(sm_register_device);
1389fc51a37a8da84618df7584cad67c078317f6720Maxim Levitsky
1399fc51a37a8da84618df7584cad67c078317f6720Maxim LevitskyMODULE_LICENSE("GPL");
1409fc51a37a8da84618df7584cad67c078317f6720Maxim LevitskyMODULE_AUTHOR("Maxim Levitsky <maximlevitsky@gmail.com>");
1419fc51a37a8da84618df7584cad67c078317f6720Maxim LevitskyMODULE_DESCRIPTION("Common SmartMedia/xD functions");
142