Skip to content

Commit

Permalink
{MTD] add support for Intel's "Sibley" flash
Browse files Browse the repository at this point in the history
This updates the Primary Vendor-Specific Extended Query parsing to
version 1.4 in order to get the information about the Configurable
Programming Mode regions implemented in the Sibley flash, as well as
selecting the appropriate write command code.

This flash does not behave like traditional NOR flash when writing data.
While mtdblock should just work, further changes are needed for JFFS2 use.

Signed-off-by: Nicolas Pitre <[email protected]>
Signed-off-by: Thomas Gleixner <[email protected]>
  • Loading branch information
Nicolas Pitre authored and Thomas Gleixner committed Nov 6, 2005
1 parent 4843653 commit 638d983
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 29 deletions.
88 changes: 65 additions & 23 deletions drivers/mtd/chips/cfi_cmdset_0001.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*
* (C) 2000 Red Hat. GPL'd
*
* $Id: cfi_cmdset_0001.c,v 1.181 2005/08/06 04:16:48 nico Exp $
* $Id: cfi_cmdset_0001.c,v 1.182 2005/08/06 04:40:41 nico Exp $
*
*
* 10/10/2000 Nicolas Pitre <[email protected]>
Expand Down Expand Up @@ -105,6 +105,7 @@ static struct mtd_chip_driver cfi_intelext_chipdrv = {
static void cfi_tell_features(struct cfi_pri_intelext *extp)
{
int i;
printk(" Extended Query version %c.%c\n", extp->MajorVersion, extp->MinorVersion);
printk(" Feature/Command Support: %4.4X\n", extp->FeatureSupport);
printk(" - Chip Erase: %s\n", extp->FeatureSupport&1?"supported":"unsupported");
printk(" - Suspend Erase: %s\n", extp->FeatureSupport&2?"supported":"unsupported");
Expand All @@ -116,7 +117,8 @@ static void cfi_tell_features(struct cfi_pri_intelext *extp)
printk(" - Page-mode read: %s\n", extp->FeatureSupport&128?"supported":"unsupported");
printk(" - Synchronous read: %s\n", extp->FeatureSupport&256?"supported":"unsupported");
printk(" - Simultaneous operations: %s\n", extp->FeatureSupport&512?"supported":"unsupported");
for (i=10; i<32; i++) {
printk(" - Extended Flash Array: %s\n", extp->FeatureSupport&1024?"supported":"unsupported");
for (i=11; i<32; i++) {
if (extp->FeatureSupport & (1<<i))
printk(" - Unknown Bit %X: supported\n", i);
}
Expand All @@ -130,12 +132,18 @@ static void cfi_tell_features(struct cfi_pri_intelext *extp)

printk(" Block Status Register Mask: %4.4X\n", extp->BlkStatusRegMask);
printk(" - Lock Bit Active: %s\n", extp->BlkStatusRegMask&1?"yes":"no");
printk(" - Valid Bit Active: %s\n", extp->BlkStatusRegMask&2?"yes":"no");
for (i=2; i<16; i++) {
printk(" - Lock-Down Bit Active: %s\n", extp->BlkStatusRegMask&2?"yes":"no");
for (i=2; i<3; i++) {
if (extp->BlkStatusRegMask & (1<<i))
printk(" - Unknown Bit %X Active: yes\n",i);
}

printk(" - EFA Lock Bit: %s\n", extp->BlkStatusRegMask&16?"yes":"no");
printk(" - EFA Lock-Down Bit: %s\n", extp->BlkStatusRegMask&32?"yes":"no");
for (i=6; i<16; i++) {
if (extp->BlkStatusRegMask & (1<<i))
printk(" - Unknown Bit %X Active: yes\n",i);
}

printk(" Vcc Logic Supply Optimum Program/Erase Voltage: %d.%d V\n",
extp->VccOptimal >> 4, extp->VccOptimal & 0xf);
if (extp->VppOptimal)
Expand Down Expand Up @@ -253,7 +261,7 @@ read_pri_intelext(struct map_info *map, __u16 adr)
return NULL;

if (extp->MajorVersion != '1' ||
(extp->MinorVersion < '0' || extp->MinorVersion > '3')) {
(extp->MinorVersion < '0' || extp->MinorVersion > '4')) {
printk(KERN_ERR " Unknown Intel/Sharp Extended Query "
"version %c.%c.\n", extp->MajorVersion,
extp->MinorVersion);
Expand All @@ -266,7 +274,7 @@ read_pri_intelext(struct map_info *map, __u16 adr)
extp->BlkStatusRegMask = le16_to_cpu(extp->BlkStatusRegMask);
extp->ProtRegAddr = le16_to_cpu(extp->ProtRegAddr);

if (extp->MajorVersion == '1' && extp->MinorVersion == '3') {
if (extp->MajorVersion == '1' && extp->MinorVersion >= '3') {
unsigned int extra_size = 0;
int nb_parts, i;

Expand All @@ -275,14 +283,18 @@ read_pri_intelext(struct map_info *map, __u16 adr)
sizeof(struct cfi_intelext_otpinfo);

/* Burst Read info */
extra_size += 6;
extra_size += (extp->MinorVersion < '4') ? 6 : 5;

/* Number of hardware-partitions */
extra_size += 1;
if (extp_size < sizeof(*extp) + extra_size)
goto need_more;
nb_parts = extp->extra[extra_size - 1];

/* skip the sizeof(partregion) field in CFI 1.4 */
if (extp->MinorVersion >= '4')
extra_size += 2;

for (i = 0; i < nb_parts; i++) {
struct cfi_intelext_regioninfo *rinfo;
rinfo = (struct cfi_intelext_regioninfo *)&extp->extra[extra_size];
Expand All @@ -294,6 +306,9 @@ read_pri_intelext(struct map_info *map, __u16 adr)
* sizeof(struct cfi_intelext_blockinfo);
}

if (extp->MinorVersion >= '4')
extra_size += sizeof(struct cfi_intelext_programming_regioninfo);

if (extp_size < sizeof(*extp) + extra_size) {
need_more:
extp_size = sizeof(*extp) + extra_size;
Expand Down Expand Up @@ -490,7 +505,7 @@ static int cfi_intelext_partition_fixup(struct mtd_info *mtd,
* arrangement at this point. This can be rearranged in the future
* if someone feels motivated enough. --nico
*/
if (extp && extp->MajorVersion == '1' && extp->MinorVersion == '3'
if (extp && extp->MajorVersion == '1' && extp->MinorVersion >= '3'
&& extp->FeatureSupport & (1 << 9)) {
struct cfi_private *newcfi;
struct flchip *chip;
Expand All @@ -502,12 +517,16 @@ static int cfi_intelext_partition_fixup(struct mtd_info *mtd,
sizeof(struct cfi_intelext_otpinfo);

/* Burst Read info */
offs += 6;
offs += (extp->MinorVersion < '4') ? 6 : 5;

/* Number of partition regions */
numregions = extp->extra[offs];
offs += 1;

/* skip the sizeof(partregion) field in CFI 1.4 */
if (extp->MinorVersion >= '4')
offs += 2;

/* Number of hardware partitions */
numparts = 0;
for (i = 0; i < numregions; i++) {
Expand All @@ -519,6 +538,20 @@ static int cfi_intelext_partition_fixup(struct mtd_info *mtd,
sizeof(struct cfi_intelext_blockinfo);
}

/* Programming Region info */
if (extp->MinorVersion >= '4') {
struct cfi_intelext_programming_regioninfo *prinfo;
prinfo = (struct cfi_intelext_programming_regioninfo *)&extp->extra[offs];
MTD_PROGREGION_SIZE(mtd) = cfi->interleave << prinfo->ProgRegShift;
MTD_PROGREGION_CTRLMODE_VALID(mtd) = cfi->interleave * prinfo->ControlValid;
MTD_PROGREGION_CTRLMODE_INVALID(mtd) = cfi->interleave * prinfo->ControlInvalid;
mtd->flags |= MTD_PROGRAM_REGIONS;
printk(KERN_DEBUG "%s: program region size/ctrl_valid/ctrl_inval = %d/%d/%d\n",
map->name, MTD_PROGREGION_SIZE(mtd),
MTD_PROGREGION_CTRLMODE_VALID(mtd),
MTD_PROGREGION_CTRLMODE_INVALID(mtd));
}

/*
* All functions below currently rely on all chips having
* the same geometry so we'll just assume that all hardware
Expand Down Expand Up @@ -1222,12 +1255,17 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,

adr += chip->start;

/* Let's determine this according to the interleave only once */
/* Let's determine those according to the interleave only once */
status_OK = CMD(0x80);
switch (mode) {
case FL_WRITING: write_cmd = CMD(0x40); break;
case FL_OTP_WRITE: write_cmd = CMD(0xc0); break;
default: return -EINVAL;
case FL_WRITING:
write_cmd = (cfi->cfiq->P_ID != 0x0200) ? CMD(0x40) : CMD(0x41);
break;
case FL_OTP_WRITE:
write_cmd = CMD(0xc0);
break;
default:
return -EINVAL;
}

spin_lock(chip->mutex);
Expand Down Expand Up @@ -1410,16 +1448,17 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
unsigned long adr, const u_char *buf, int len)
{
struct cfi_private *cfi = map->fldrv_priv;
map_word status, status_OK;
map_word status, status_OK, write_cmd;
unsigned long cmd_adr, timeo;
int wbufsize, z, ret=0, bytes, words;

wbufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize;
adr += chip->start;
cmd_adr = adr & ~(wbufsize-1);

/* Let's determine this according to the interleave only once */
status_OK = CMD(0x80);
write_cmd = (cfi->cfiq->P_ID != 0x0200) ? CMD(0xe8) : CMD(0xe9);

spin_lock(chip->mutex);
ret = get_chip(map, chip, cmd_adr, FL_WRITING);
Expand Down Expand Up @@ -1451,7 +1490,7 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,

z = 0;
for (;;) {
map_write(map, CMD(0xe8), cmd_adr);
map_write(map, write_cmd, cmd_adr);

status = map_read(map, cmd_adr);
if (map_word_andequal(map, status, status_OK, status_OK))
Expand Down Expand Up @@ -2380,20 +2419,23 @@ static void cfi_intelext_destroy(struct mtd_info *mtd)
kfree(mtd->eraseregions);
}

static char im_name_1[]="cfi_cmdset_0001";
static char im_name_3[]="cfi_cmdset_0003";
static char im_name_0001[] = "cfi_cmdset_0001";
static char im_name_0003[] = "cfi_cmdset_0003";
static char im_name_0200[] = "cfi_cmdset_0200";

static int __init cfi_intelext_init(void)
{
inter_module_register(im_name_1, THIS_MODULE, &cfi_cmdset_0001);
inter_module_register(im_name_3, THIS_MODULE, &cfi_cmdset_0001);
inter_module_register(im_name_0001, THIS_MODULE, &cfi_cmdset_0001);
inter_module_register(im_name_0003, THIS_MODULE, &cfi_cmdset_0001);
inter_module_register(im_name_0200, THIS_MODULE, &cfi_cmdset_0001);
return 0;
}

static void __exit cfi_intelext_exit(void)
{
inter_module_unregister(im_name_1);
inter_module_unregister(im_name_3);
inter_module_unregister(im_name_0001);
inter_module_unregister(im_name_0003);
inter_module_unregister(im_name_0200);
}

module_init(cfi_intelext_init);
Expand Down
3 changes: 2 additions & 1 deletion drivers/mtd/chips/gen_probe.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* Routines common to all CFI-type probes.
* (C) 2001-2003 Red Hat, Inc.
* GPL'd
* $Id: gen_probe.c,v 1.22 2005/01/24 23:49:50 rmk Exp $
* $Id: gen_probe.c,v 1.23 2005/08/06 04:40:41 nico Exp $
*/

#include <linux/kernel.h>
Expand Down Expand Up @@ -235,6 +235,7 @@ static struct mtd_info *check_cmd_set(struct map_info *map, int primary)
#ifdef CONFIG_MTD_CFI_INTELEXT
case 0x0001:
case 0x0003:
case 0x0200:
return cfi_cmdset_0001(map, primary);
#endif
#ifdef CONFIG_MTD_CFI_AMDSTD
Expand Down
13 changes: 11 additions & 2 deletions include/linux/mtd/cfi.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

/* Common Flash Interface structures
* See http://support.intel.com/design/flash/technote/index.htm
* $Id: cfi.h,v 1.54 2005/06/06 23:04:36 tpoynor Exp $
* $Id: cfi.h,v 1.55 2005/08/06 04:40:42 nico Exp $
*/

#ifndef __MTD_CFI_H__
Expand Down Expand Up @@ -173,6 +173,15 @@ struct cfi_intelext_regioninfo {
struct cfi_intelext_blockinfo BlockTypes[1];
} __attribute__((packed));

struct cfi_intelext_programming_regioninfo {
uint8_t ProgRegShift;
uint8_t Reserved1;
uint8_t ControlValid;
uint8_t Reserved2;
uint8_t ControlInvalid;
uint8_t Reserved3;
} __attribute__((packed));

/* Vendor-Specific PRI for AMD/Fujitsu Extended Command Set (0x0002) */

struct cfi_pri_amdstd {
Expand Down Expand Up @@ -316,7 +325,7 @@ static inline map_word cfi_build_cmd(u_long cmd, struct map_info *map, struct cf
#define CMD(x) cfi_build_cmd((x), map, cfi)


static inline unsigned char cfi_merge_status(map_word val, struct map_info *map,
static inline unsigned long cfi_merge_status(map_word val, struct map_info *map,
struct cfi_private *cfi)
{
int wordwidth, words_per_bus, chip_mode, chips_per_word;
Expand Down
14 changes: 12 additions & 2 deletions include/linux/mtd/mtd.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* $Id: mtd.h,v 1.59 2005/04/11 10:19:02 gleixner Exp $
* $Id: mtd.h,v 1.60 2005/08/06 04:40:42 nico Exp $
*
* Copyright (C) 1999-2003 David Woodhouse <[email protected]> et al.
*
Expand Down Expand Up @@ -72,7 +72,17 @@ struct mtd_info {
u_int32_t oobsize; // Amount of OOB data per block (e.g. 16)
u_int32_t ecctype;
u_int32_t eccsize;


/*
* Reuse some of the above unused fields in the case of NOR flash
* with configurable programming regions to avoid modifying the
* user visible structure layout/size. Only valid when the
* MTD_PROGRAM_REGIONS flag is set.
* (Maybe we should have an union for those?)
*/
#define MTD_PROGREGION_SIZE(mtd) (mtd)->oobblock
#define MTD_PROGREGION_CTRLMODE_VALID(mtd) (mtd)->oobsize
#define MTD_PROGREGION_CTRLMODE_INVALID(mtd) (mtd)->ecctype

// Kernel-only stuff starts here.
char *name;
Expand Down
3 changes: 2 additions & 1 deletion include/mtd/mtd-abi.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* $Id: mtd-abi.h,v 1.11 2005/05/19 16:08:58 gleixner Exp $
* $Id: mtd-abi.h,v 1.12 2005/08/06 04:40:43 nico Exp $
*
* Portions of MTD ABI definition which are shared by kernel and user space
*/
Expand Down Expand Up @@ -42,6 +42,7 @@ struct mtd_oob_buf {
#define MTD_OOB 64 // Out-of-band data (NAND flash)
#define MTD_ECC 128 // Device capable of automatic ECC
#define MTD_NO_VIRTBLOCKS 256 // Virtual blocks not allowed
#define MTD_PROGRAM_REGIONS 512 // Configurable Programming Regions

// Some common devices / combinations of capabilities
#define MTD_CAP_ROM 0
Expand Down

0 comments on commit 638d983

Please sign in to comment.