Commit f77814dd authored by Nicolas Pitre's avatar Nicolas Pitre Committed by Thomas Gleixner

[MTD] Support for protection register support on Intel FLASH chips

This enables support for reading, writing and locking so called
"Protection Registers" present on some flash chips.
A subset of them are pre-programmed at the factory with a
unique set of values. The rest is user-programmable.
Signed-off-by: default avatarNicolas Pitre <nico@cam.org>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
parent 67d9e95c
# drivers/mtd/chips/Kconfig # drivers/mtd/chips/Kconfig
# $Id: Kconfig,v 1.13 2004/12/01 15:49:10 nico Exp $ # $Id: Kconfig,v 1.14 2005/02/08 17:11:15 nico Exp $
menu "RAM/ROM/Flash chip drivers" menu "RAM/ROM/Flash chip drivers"
depends on MTD!=n depends on MTD!=n
...@@ -155,6 +155,31 @@ config MTD_CFI_I8 ...@@ -155,6 +155,31 @@ config MTD_CFI_I8
If your flash chips are interleaved in eights - i.e. you have eight If your flash chips are interleaved in eights - i.e. you have eight
flash chips addressed by each bus cycle, then say 'Y'. flash chips addressed by each bus cycle, then say 'Y'.
config MTD_OTP
bool "Protection Registers aka one-time programmable (OTP) bits"
depends on MTD_CFI_ADV_OPTIONS
default n
help
This enables support for reading, writing and locking so called
"Protection Registers" present on some flash chips.
A subset of them are pre-programmed at the factory with a
unique set of values. The rest is user-programmable.
The user-programmable Protection Registers contain one-time
programmable (OTP) bits; when programmed, register bits cannot be
erased. Each Protection Register can be accessed multiple times to
program individual bits, as long as the register remains unlocked.
Each Protection Register has an associated Lock Register bit. When a
Lock Register bit is programmed, the associated Protection Register
can only be read; it can no longer be programmed. Additionally,
because the Lock Register bits themselves are OTP, when programmed,
Lock Register bits cannot be erased. Therefore, when a Protection
Register is locked, it cannot be unlocked.
This feature should therefore be used with extreme care. Any mistake
in the programming of OTP bits will waste them.
config MTD_CFI_INTELEXT config MTD_CFI_INTELEXT
tristate "Support for Intel/Sharp flash chips" tristate "Support for Intel/Sharp flash chips"
depends on MTD_GEN_PROBE depends on MTD_GEN_PROBE
......
This diff is collapsed.
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* *
* This code is GPL * This code is GPL
* *
* $Id: mtdpart.c,v 1.51 2004/11/16 18:28:59 dwmw2 Exp $ * $Id: mtdpart.c,v 1.53 2005/02/08 17:11:13 nico Exp $
* *
* 02-21-2002 Thomas Gleixner <gleixner@autronix.de> * 02-21-2002 Thomas Gleixner <gleixner@autronix.de>
* added support for read_oob, write_oob * added support for read_oob, write_oob
...@@ -116,6 +116,13 @@ static int part_read_user_prot_reg (struct mtd_info *mtd, loff_t from, size_t le ...@@ -116,6 +116,13 @@ static int part_read_user_prot_reg (struct mtd_info *mtd, loff_t from, size_t le
len, retlen, buf); len, retlen, buf);
} }
static int part_get_user_prot_info (struct mtd_info *mtd,
struct otp_info *buf, size_t len)
{
struct mtd_part *part = PART(mtd);
return part->master->get_user_prot_info (part->master, buf, len);
}
static int part_read_fact_prot_reg (struct mtd_info *mtd, loff_t from, size_t len, static int part_read_fact_prot_reg (struct mtd_info *mtd, loff_t from, size_t len,
size_t *retlen, u_char *buf) size_t *retlen, u_char *buf)
{ {
...@@ -124,6 +131,13 @@ static int part_read_fact_prot_reg (struct mtd_info *mtd, loff_t from, size_t le ...@@ -124,6 +131,13 @@ static int part_read_fact_prot_reg (struct mtd_info *mtd, loff_t from, size_t le
len, retlen, buf); len, retlen, buf);
} }
static int part_get_fact_prot_info (struct mtd_info *mtd,
struct otp_info *buf, size_t len)
{
struct mtd_part *part = PART(mtd);
return part->master->get_fact_prot_info (part->master, buf, len);
}
static int part_write (struct mtd_info *mtd, loff_t to, size_t len, static int part_write (struct mtd_info *mtd, loff_t to, size_t len,
size_t *retlen, const u_char *buf) size_t *retlen, const u_char *buf)
{ {
...@@ -182,6 +196,12 @@ static int part_write_user_prot_reg (struct mtd_info *mtd, loff_t from, size_t l ...@@ -182,6 +196,12 @@ static int part_write_user_prot_reg (struct mtd_info *mtd, loff_t from, size_t l
len, retlen, buf); len, retlen, buf);
} }
static int part_lock_user_prot_reg (struct mtd_info *mtd, loff_t from, size_t len)
{
struct mtd_part *part = PART(mtd);
return part->master->lock_user_prot_reg (part->master, from, len);
}
static int part_writev (struct mtd_info *mtd, const struct kvec *vecs, static int part_writev (struct mtd_info *mtd, const struct kvec *vecs,
unsigned long count, loff_t to, size_t *retlen) unsigned long count, loff_t to, size_t *retlen)
{ {
...@@ -409,6 +429,12 @@ int add_mtd_partitions(struct mtd_info *master, ...@@ -409,6 +429,12 @@ int add_mtd_partitions(struct mtd_info *master,
slave->mtd.read_fact_prot_reg = part_read_fact_prot_reg; slave->mtd.read_fact_prot_reg = part_read_fact_prot_reg;
if(master->write_user_prot_reg) if(master->write_user_prot_reg)
slave->mtd.write_user_prot_reg = part_write_user_prot_reg; slave->mtd.write_user_prot_reg = part_write_user_prot_reg;
if(master->lock_user_prot_reg)
slave->mtd.lock_user_prot_reg = part_lock_user_prot_reg;
if(master->get_user_prot_info)
slave->mtd.get_user_prot_info = part_get_user_prot_info;
if(master->get_fact_prot_info)
slave->mtd.get_fact_prot_info = part_get_fact_prot_info;
if (master->sync) if (master->sync)
slave->mtd.sync = part_sync; slave->mtd.sync = part_sync;
if (!i && master->suspend && master->resume) { if (!i && master->suspend && master->resume) {
......
/* Common Flash Interface structures /* Common Flash Interface structures
* See http://support.intel.com/design/flash/technote/index.htm * See http://support.intel.com/design/flash/technote/index.htm
* $Id: cfi.h,v 1.51 2005/02/05 02:06:16 nico Exp $ * $Id: cfi.h,v 1.52 2005/02/08 17:11:15 nico Exp $
*/ */
#ifndef __MTD_CFI_H__ #ifndef __MTD_CFI_H__
...@@ -252,7 +252,7 @@ static inline uint32_t cfi_build_cmd_addr(uint32_t cmd_ofs, int interleave, int ...@@ -252,7 +252,7 @@ static inline uint32_t cfi_build_cmd_addr(uint32_t cmd_ofs, int interleave, int
* It looks too long to be inline, but in the common case it should almost all * It looks too long to be inline, but in the common case it should almost all
* get optimised away. * get optimised away.
*/ */
static inline map_word cfi_build_cmd(u_char cmd, struct map_info *map, struct cfi_private *cfi) static inline map_word cfi_build_cmd(u_long cmd, struct map_info *map, struct cfi_private *cfi)
{ {
map_word val = { {0} }; map_word val = { {0} };
int wordwidth, words_per_bus, chip_mode, chips_per_word; int wordwidth, words_per_bus, chip_mode, chips_per_word;
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* *
* (C) 2000 Red Hat. GPLd. * (C) 2000 Red Hat. GPLd.
* *
* $Id: flashchip.h,v 1.15 2004/11/05 22:41:06 nico Exp $ * $Id: flashchip.h,v 1.16 2005/02/08 17:11:15 nico Exp $
* *
*/ */
...@@ -29,6 +29,7 @@ typedef enum { ...@@ -29,6 +29,7 @@ typedef enum {
FL_ERASE_SUSPENDED, FL_ERASE_SUSPENDED,
FL_WRITING, FL_WRITING,
FL_WRITING_TO_BUFFER, FL_WRITING_TO_BUFFER,
FL_OTP_WRITE,
FL_WRITE_SUSPENDING, FL_WRITE_SUSPENDING,
FL_WRITE_SUSPENDED, FL_WRITE_SUSPENDED,
FL_PM_SUSPENDED, FL_PM_SUSPENDED,
......
/* Overhauled routines for dealing with different mmap regions of flash */ /* Overhauled routines for dealing with different mmap regions of flash */
/* $Id: map.h,v 1.46 2005/01/05 17:09:44 dwmw2 Exp $ */ /* $Id: map.h,v 1.47 2005/02/08 17:11:15 nico Exp $ */
#ifndef __LINUX_MTD_MAP_H__ #ifndef __LINUX_MTD_MAP_H__
#define __LINUX_MTD_MAP_H__ #define __LINUX_MTD_MAP_H__
...@@ -263,6 +263,17 @@ static inline map_word map_word_and(struct map_info *map, map_word val1, map_wor ...@@ -263,6 +263,17 @@ static inline map_word map_word_and(struct map_info *map, map_word val1, map_wor
return r; return r;
} }
static inline map_word map_word_clr(struct map_info *map, map_word val1, map_word val2)
{
map_word r;
int i;
for (i=0; i<map_words(map); i++) {
r.x[i] = val1.x[i] & ~val2.x[i];
}
return r;
}
static inline map_word map_word_or(struct map_info *map, map_word val1, map_word val2) static inline map_word map_word_or(struct map_info *map, map_word val1, map_word val2)
{ {
map_word r; map_word r;
...@@ -273,6 +284,7 @@ static inline map_word map_word_or(struct map_info *map, map_word val1, map_word ...@@ -273,6 +284,7 @@ static inline map_word map_word_or(struct map_info *map, map_word val1, map_word
} }
return r; return r;
} }
#define map_word_andequal(m, a, b, z) map_word_equal(m, z, map_word_and(m, a, b)) #define map_word_andequal(m, a, b, z) map_word_equal(m, z, map_word_and(m, a, b))
static inline int map_word_bitsset(struct map_info *map, map_word val1, map_word val2) static inline int map_word_bitsset(struct map_info *map, map_word val1, map_word val2)
...@@ -338,6 +350,7 @@ static inline map_word map_word_ff(struct map_info *map) ...@@ -338,6 +350,7 @@ static inline map_word map_word_ff(struct map_info *map)
} }
return r; return r;
} }
static inline map_word inline_map_read(struct map_info *map, unsigned long ofs) static inline map_word inline_map_read(struct map_info *map, unsigned long ofs)
{ {
map_word r; map_word r;
......
/* /*
* $Id: mtd.h,v 1.56 2004/08/09 18:46:04 dmarlin Exp $ * $Id: mtd.h,v 1.57 2005/02/08 17:11:15 nico Exp $
* *
* Copyright (C) 1999-2003 David Woodhouse <dwmw2@infradead.org> et al. * Copyright (C) 1999-2003 David Woodhouse <dwmw2@infradead.org> et al.
* *
...@@ -113,12 +113,12 @@ struct mtd_info { ...@@ -113,12 +113,12 @@ struct mtd_info {
* flash devices. The user data is one time programmable but the * flash devices. The user data is one time programmable but the
* factory data is read only. * factory data is read only.
*/ */
int (*read_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); int (*get_fact_prot_info) (struct mtd_info *mtd, struct otp_info *buf, size_t len);
int (*read_fact_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); int (*read_fact_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
int (*get_user_prot_info) (struct mtd_info *mtd, struct otp_info *buf, size_t len);
/* This function is not yet implemented */ int (*read_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
int (*write_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); int (*write_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
int (*lock_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len);
/* kvec-based read/write methods. We need these especially for NAND flash, /* kvec-based read/write methods. We need these especially for NAND flash,
with its limited number of write cycles per erase. with its limited number of write cycles per erase.
......
/* /*
* $Id: mtd-abi.h,v 1.7 2004/11/23 15:37:32 gleixner Exp $ * $Id: mtd-abi.h,v 1.8 2005/02/08 17:11:16 nico Exp $
* *
* Portions of MTD ABI definition which are shared by kernel and user space * Portions of MTD ABI definition which are shared by kernel and user space
*/ */
...@@ -80,6 +80,12 @@ struct region_info_user { ...@@ -80,6 +80,12 @@ struct region_info_user {
uint32_t regionindex; uint32_t regionindex;
}; };
struct otp_info {
uint32_t start;
uint32_t length;
uint32_t locked;
};
#define MEMGETINFO _IOR('M', 1, struct mtd_info_user) #define MEMGETINFO _IOR('M', 1, struct mtd_info_user)
#define MEMERASE _IOW('M', 2, struct erase_info_user) #define MEMERASE _IOW('M', 2, struct erase_info_user)
#define MEMWRITEOOB _IOWR('M', 3, struct mtd_oob_buf) #define MEMWRITEOOB _IOWR('M', 3, struct mtd_oob_buf)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment