[HTC Wildfire S] tacromx:
Nand

Here goes...my first post

I hope this is of some relevance to someone, it's concerning the nand mtd driver from the wfs kernel source, it's just an extract, there's lots of interesting references in there, this one in particular is part of nand_base.c, just an extract.

Hope it helps.

/**

* __nand_unlock - [REPLACABLE] unlocks specified locked blockes

*

* @param mtd - mtd info

* @param ofs - offset to start unlock from

* @param len - length to unlock

* @invert - when = 0, unlock the range of blocks within the lower and

* upper boundary address

* whne = 1, unlock the range of blocks outside the boundaries

* of the lower and upper boundary address

*

* @return - unlock status

*/

static int __nand_unlock(struct mtd_info *mtd, loff_t ofs,

uint64_t len, int invert)

{

int ret = 0;

int status, page;

struct nand_chip *chip = mtd->priv;

/* Submit address of first page to unlock */

page = ofs >> chip->page_shift;

chip->cmdfunc(mtd, NAND_CMD_UNLOCK1, -1, page & chip->pagemask);

/* Submit address of last page to unlock */

page = (ofs + len) >> chip->page_shift;

chip->cmdfunc(mtd, NAND_CMD_UNLOCK2, -1,

(page | invert) & chip->pagemask);

/* Call wait ready function */

status = chip->waitfunc(mtd, chip);

udelay(1000);

/* See if device thinks it succeeded */

if (status & 0x01) {

DEBUG(MTD_DEBUG_LEVEL0, "%s: Error status = 0x%08x\n",

__func__, status);

ret = -EIO;

}

return ret;

}

/**

* nand_unlock - [REPLACABLE] unlocks specified locked blockes

*

* @param mtd - mtd info

* @param ofs - offset to start unlock from

* @param len - length to unlock

*

* @return - unlock status

*/

int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)

{

int ret = 0;

int chipnr;

struct nand_chip *chip = mtd->priv;

DEBUG(MTD_DEBUG_LEVEL3, "%s: start = 0x%012llx, len = %llu\n",

__func__, (unsigned long long)ofs, len);

if (check_offs_len(mtd, ofs, len))

ret = -EINVAL;

/* Align to last block address if size addresses end of the device */

if (ofs + len == mtd->size)

len -= mtd->erasesize;

nand_get_device(chip, mtd, FL_UNLOCKING);

/* Shift to get chip number */

chipnr = ofs >> chip->chip_shift;

chip->select_chip(mtd, chipnr);

/* Check, if it is write protected */

if (nand_check_wp(mtd)) {

DEBUG(MTD_DEBUG_LEVEL0, "%s: Device is write protected!!!\n",

__func__);

ret = -EIO;

goto out;

}

ret = __nand_unlock(mtd, ofs, len, 0);

out:

/* de-select the NAND device */

chip->select_chip(mtd, -1);

nand_release_device(mtd);

return ret;

}

/**

* nand_lock - [REPLACABLE] locks all blockes present in the device

*

* @param mtd - mtd info

* @param ofs - offset to start unlock from

* @param len - length to unlock

*

* @return - lock status

*

* This feature is not support in many NAND parts. 'Micron' NAND parts

* do have this feature, but it allows only to lock all blocks not for

* specified range for block.

*

* Implementing 'lock' feature by making use of 'unlock', for now.

*/

int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)

{

int ret = 0;

int chipnr, status, page;

struct nand_chip *chip = mtd->priv;

DEBUG(MTD_DEBUG_LEVEL3, "%s: start = 0x%012llx, len = %llu\n",

__func__, (unsigned long long)ofs, len);

if (check_offs_len(mtd, ofs, len))

ret = -EINVAL;

nand_get_device(chip, mtd, FL_LOCKING);

/* Shift to get chip number */

chipnr = ofs >> chip->chip_shift;

chip->select_chip(mtd, chipnr);

/* Check, if it is write protected */

if (nand_check_wp(mtd)) {

DEBUG(MTD_DEBUG_LEVEL0, "%s: Device is write protected!!!\n",

__func__);

status = MTD_ERASE_FAILED;

ret = -EIO;

goto out;

}

/* Submit address of first page to lock */

page = ofs >> chip->page_shift;

chip->cmdfunc(mtd, NAND_CMD_LOCK, -1, page & chip->pagemask);

/* Call wait ready function */

status = chip->waitfunc(mtd, chip);

udelay(1000);

/* See if device thinks it succeeded */

if (status & 0x01) {

DEBUG(MTD_DEBUG_LEVEL0, "%s: Error status = 0x%08x\n",

__func__, status);

ret = -EIO;

goto out;

}

ret = __nand_unlock(mtd, ofs, len, 0x1);

out:

/* de-select the NAND device */

chip->select_chip(mtd, -1);

nand_release_device(mtd);

return ret;

}