From: David Woodhouse <dwmw2@infradead.org>
To: mtd@infradead.org
Subject: Common Flash Interface probe code.
Date: Mon, 12 Jun 2000 13:04:50 +0100 [thread overview]
Message-ID: <30028.960811490@cygnus.co.uk> (raw)
Anyone with memory-mapped CFI-compliant NOR flash, especially if it's not
in 16-bit mode like the one I'm testing on - could you test this probe code
for me?
/*
Common Flash Interface probe code.
(C) 2000 Red Hat. GPL'd.
$Id$
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <asm/io.h>
#include <asm/byteorder.h>
#include <linux/errno.h>
#ifdef __arm__
/* Shoot me. Better still, shoot rmk. dwmw2 */
#undef writeb
#undef writew
#undef readb
#undef readw
#define readb(l) (*(unsigned char *)(l))
#define writeb(c,l) do {*((unsigned char *)(l)) = (c);} while (0)
#define readw(l) (*(unsigned short *)(l))
#define writew(c,l) do {*((unsigned short *)(l)) = (c);} while (0)
/* It's OK. You can look back now. */
#endif /* __arm__ */
struct cfi_ident {
__u8 qry[3];
__u16 P_ID;
__u16 P;
__u16 A_ID;
__u16 A;
__u8 VccMin;
__u8 VccMax;
__u8 VppMin;
__u8 VppMax;
__u8 WordWriteTimeoutTyp;
__u8 BufWriteTimeoutTyp;
__u8 BlockEraseTimeoutTyp;
__u8 ChipEraseTimeoutTyp;
__u8 WordWriteTimeoutMax;
__u8 BufWriteTimeoutMax;
__u8 BlockEraseTimeoutMax;
__u8 ChipEraseTimeoutMax;
__u8 DevSize;
__u16 InterfaceDesc;
__u16 MaxBufWriteSize;
__u8 NumEraseRegions;
__u32 EraseRegionInfo[1];
} __attribute__((packed));
void print_cfi_ident(struct cfi_ident *cfip);
int init_module(void)
{
unsigned char tmpzero;
unsigned long base = 0xd0000000;
int devwidth=0, numdevs=0;
int i;
struct cfi_ident cfip;
tmpzero=readb(base);
writeb(0x98, base+0x55);
if (*(unsigned char*) (base + 0x10) == 'Q' &&
*(unsigned char*) (base + 0x11) == 'R' &&
*(unsigned char*) (base + 0x12) == 'Y') {
printk("Found a CFI device at location %lx in 8 bit mode\n", base);
devwidth=1;
numdevs=1;
}
if (!devwidth) {
writew(0x9898, base+0xAA);
if (*(__u16*) (base + 0x20) == cpu_to_le16(0x0051) &&
*(__u16*) (base + 0x22) == cpu_to_le16(0x0052) &&
*(__u16*) (base + 0x24) == cpu_to_le16(0x0059)) {
printk("Found a CFI device at location %lx in 16 bit mode\n", base);
devwidth=2;
numdevs=1;
}
else if (*(__u16*) (base + 0x20) == 0x5151 &&
*(__u16*) (base + 0x22) == 0x5252 &&
*(__u16*) (base + 0x24) == 0x5959) {
printk("Found a coupled pair of CFI devices at location %lx in 8 bit mode\n", base);
devwidth=2;
numdevs=2;
}
}
if (!devwidth) {
writel(0x98989898, base+0x154);
if (*(__u32*) (base + 0x40) == cpu_to_le32(0x00000051) &&
*(__u32*) (base + 0x44) == cpu_to_le32(0x00000052) &&
*(__u32*) (base + 0x48) == cpu_to_le32(0x00000059)) {
/* This isn't actually in the CFI spec - only x8 and x16 are. */
printk("Found a CFI-like device at location %lx which appears to be in 32 bit mode(!)\n", base);
devwidth=4;
numdevs=1;
}
else if (*(__u32*) (base + 0x40) == cpu_to_le32(0x00510051) &&
*(__u32*) (base + 0x44) == cpu_to_le32(0x00520052) &&
*(__u32*) (base + 0x48) == cpu_to_le32(0x00590059)) {
printk("Found a coupled pair of CFI devices at location %lx in 16 bit mode\n", base);
devwidth=4;
numdevs=2;
}
else if (*(__u32*) (base + 0x40) == 0x51515151 &&
*(__u32*) (base + 0x44) == 0x52525252 &&
*(__u32*) (base + 0x48) == 0x59595959) {
printk("Found four side-by-side CFI devices at location %lx in 8 bit mode\n", base);
devwidth=4;
numdevs=4;
}
}
/* We won't bother with 64-bit wide detection at the moment */
if (!devwidth) {
printk("Found no CFI device at location %lx\n", base);
return -ENXIO;
}
for (i=0; i<sizeof(struct cfi_ident); i++) {
((unsigned char *)&cfip)[i] = *(unsigned char *) (base + ((0x10 + i)*devwidth));
}
#if 0
for (i=0; i<8; i++) {
printk ("CFI[%2.2X]: %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n",
i*8,
((unsigned char *)&cfip)[(i*8)+0],
((unsigned char *)&cfip)[(i*8)+1],
((unsigned char *)&cfip)[(i*8)+2],
((unsigned char *)&cfip)[(i*8)+3],
((unsigned char *)&cfip)[(i*8)+4],
((unsigned char *)&cfip)[(i*8)+5],
((unsigned char *)&cfip)[(i*8)+6],
((unsigned char *)&cfip)[(i*8)+7]
);
}
#endif
print_cfi_ident(&cfip);
for (i=0; i<cfip.NumEraseRegions; i++) {
__u16 EraseRegionInfoNum = (*(unsigned char *) (base + ((0x2d + (4*i))*devwidth))) +
((*(unsigned char *) (base + ((0x2e + (4*i))*devwidth)) << 8));
__u16 EraseRegionInfoSize = (*(unsigned char *) (base + ((0x2f + (4*i))*devwidth))) +
((*(unsigned char *) (base + ((0x30 + (4*i))*devwidth)) << 8));
printk(" Erase Region #%d: BlockSize 0x%4.4X bytes, %d blocks\n",
i, EraseRegionInfoSize * 256, EraseRegionInfoNum+1);
}
return -ENXIO;
}
void print_cfi_ident(struct cfi_ident *cfip)
{
if (cfip->qry[0] == 'Q' && cfip->qry[1] == 'R' && cfip->qry[2] == 'Y') {
printk("Primary vendor: %4.4X\n", le16_to_cpu(cfip->P_ID));
printk("Alternatve vendor: %4.4X\n", le16_to_cpu(cfip->A_ID));
if (cfip->P)
printk("Primary Algorithm Table at %4.4X\n", le16_to_cpu(cfip->P));
else
printk("No Primary Algorithm Table\n");
if (cfip->A)
printk("Alternate Algorithm Table at %4.4X\n", le16_to_cpu(cfip->A));
else
printk("No Alternate Algorithm Table\n");
printk("Vcc Minimum: %x.%x V\n", cfip->VccMin >> 4, cfip->VccMin & 0xf);
printk("Vcc Maximum: %x.%x V\n", cfip->VccMax >> 4, cfip->VccMax & 0xf);
if (cfip->VppMin) {
printk("Vpp Minimum: %x.%x V\n", cfip->VppMin >> 4, cfip->VppMin & 0xf);
printk("Vpp Maximum: %x.%x V\n", cfip->VppMax >> 4, cfip->VppMax & 0xf);
}
else
printk("No Vpp line\n");
printk("Typical byte/word write timeout: %d µs\n", 1<<cfip->WordWriteTimeoutTyp);
printk("Maximum byte/word write timeout: %d µs\n", (1<<cfip->WordWriteTimeoutMax) * (1<<cfip->WordWriteTimeoutTyp));
if (cfip->BufWriteTimeoutTyp || cfip->BufWriteTimeoutMax) {
printk("Typical full buffer write timeout: %d µs\n", 1<<cfip->BufWriteTimeoutTyp);
printk("Maximum full buffer write timeout: %d µs\n", (1<<cfip->BufWriteTimeoutMax) * (1<<cfip->BufWriteTimeoutTyp));
}
else
printk("Full buffer write not supported\n");
printk("Typical block erase timeout: %d µs\n", 1<<cfip->BlockEraseTimeoutTyp);
printk("Maximum block erase timeout: %d µs\n", (1<<cfip->BlockEraseTimeoutMax) * (1<<cfip->BlockEraseTimeoutTyp));
if (cfip->ChipEraseTimeoutTyp || cfip->ChipEraseTimeoutMax) {
printk("Typical chip erase timeout: %d µs\n", 1<<cfip->ChipEraseTimeoutTyp);
printk("Maximum chip erase timeout: %d µs\n", (1<<cfip->ChipEraseTimeoutMax) * (1<<cfip->ChipEraseTimeoutTyp));
}
else
printk("Chip erase not supported\n");
printk("Device size: 0x%X bytes (%d Mb)\n", 1 << cfip->DevSize, 1<< (cfip->DevSize - 20));
printk("Flash Device Interface description: 0x%4.4X\n", le16_to_cpu(cfip->InterfaceDesc));
printk("Max. bytes in buffer write: 0x%x\n", 1<< le16_to_cpu(cfip->MaxBufWriteSize));
printk("Number of Erase Block Regions: %d\n", cfip->NumEraseRegions);
}
else printk("Invalid CFI ident structure.\n");
}
--
dwmw2
To unsubscribe, send "unsubscribe mtd" to majordomo@infradead.org
next reply other threads:[~2000-06-12 12:05 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2000-06-12 12:04 David Woodhouse [this message]
2000-06-13 5:53 ` Common Flash Interface probe code Jason Gunthorpe
2000-06-13 6:34 ` M-Systems Disk-On-Chip driver Adi Linden
2000-06-13 7:44 ` David Woodhouse
2000-06-13 13:48 ` Adi Linden
2000-06-13 14:28 ` David Woodhouse
2000-06-13 7:40 ` Common Flash Interface probe code David Woodhouse
2000-06-13 15:30 ` Jason Gunthorpe
2000-06-13 16:11 ` David Woodhouse
2000-06-13 17:16 ` Jason Gunthorpe
2000-06-13 17:54 ` David Woodhouse
-- strict thread matches above, loose matches on Subject: below --
2004-07-06 7:45 Reynolds-Lear, Matthew
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=30028.960811490@cygnus.co.uk \
--to=dwmw2@infradead.org \
--cc=mtd@infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.