From: William J Beksi <wjbeksi@setabox.com>
To: linux-mtd@lists.infradead.org
Subject: [PATCH] command function for nand flash through IDE
Date: Thu, 16 Dec 2004 21:11:11 +0800 [thread overview]
Message-ID: <41C1896F.9000107@setabox.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 233 bytes --]
Hi,
This driver includes command and select chip functions specifically for
accessing nand flash through an IDE port. Should be useful for anyone
developing and testing on a PC. It works with the latest MTD snapshot.
--
William
[-- Attachment #2: ide.c --]
[-- Type: text/x-c, Size: 5375 bytes --]
/*
* drivers/mtd/nand/ide.c
*
* Copyright (C) 2004 William J Beksi <wjbeksi@users.sourceforge.net>
*
* Derived from drivers/mtd/nand/spia.c
* Copyright (C) 2000 Steven J. Hill <sjhill@realitydiluted.com>
*
* $Id: ide.c,v 1.18 2004/12/07 05:17:46 wjbeksi Exp $
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Overview:
* This device driver allows a NAND flash device to be accessed from
* an IDE interface.
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
#include <linux/delay.h>
#include <asm/io.h>
/*
* IDE MTD structure
*/
static struct mtd_info *ide_mtd = NULL;
/*
* Values specific to the IDE
*/
#define BASEPORT1 0x1F0 /* IDE1 NAND flash I/O base address */
#define BASEPORT2 0x170 /* IDE2 NAND flash I/O base address */
#define IDE_IO_BASE BASEPORT1
/*
* Define partitions for flash device
*/
const static struct mtd_partition partition_info[] = {
{
.name = "IDE flash partition 1",
.offset = 0,
.size = 3*1024*1024
},
{
.name = "IDE flash partition 2",
.offset = 3*1024*1024,
.size = 3*1024*1024
}
};
#define NUM_PARTITIONS 2
/*
* IDE specific command function
*/
static void nand_command(struct mtd_info *mtd, unsigned command, int column, int page_addr)
{
register struct nand_chip *this = mtd->priv;
unsigned int ide_io_addr_1 = (unsigned int) this->IO_ADDR_R+1;
unsigned int ide_io_addr_2 = (unsigned int) this->IO_ADDR_R+2;
/*
* Write out the command to the device
*/
if (command == NAND_CMD_SEQIN) {
int readcmd;
if (column >= mtd->oobblock) {
/* OOB area */
column -= mtd->oobblock;
readcmd = NAND_CMD_READOOB;
} else if (column < 256) {
/* First 256 bytes --> READ0 */
readcmd = NAND_CMD_READ0;
} else {
column -= 256;
readcmd = NAND_CMD_READ1;
}
outb(readcmd, ide_io_addr_1);
}
outb(command, ide_io_addr_1);
if (column != -1 || page_addr != -1) {
/* Serially input address */
if (column != -1) {
/* Adjust columns for 16 bit buswidth */
if (this->options & NAND_BUSWIDTH_16)
column >>= 1;
outb(column, ide_io_addr_2);
}
if (page_addr != -1) {
outb((unsigned char) (page_addr & 0xff), ide_io_addr_2);
outb((unsigned char) ((page_addr >> 8) & 0xff), ide_io_addr_2);
/* One more address cycle for devices > 32MiB */
if (this->chipsize > (32 << 20))
outb((unsigned char) ((page_addr >> 16) & 0x0f),
ide_io_addr_2);
}
}
/*
* Program and erase have their own busy handlers status and sequential
* in needs no delay
*/
switch (command) {
case NAND_CMD_PAGEPROG:
case NAND_CMD_ERASE1:
case NAND_CMD_ERASE2:
case NAND_CMD_SEQIN:
case NAND_CMD_STATUS:
return;
case NAND_CMD_RESET:
if (this->dev_ready)
break;
udelay(this->chip_delay);
outb(NAND_CMD_STATUS, ide_io_addr_1);
while (!(this->read_byte(mtd) & 0x40));
return;
/* This applies to read commands */
default:
/*
* If we don't have access to the busy pin, we apply the given
* command delay
*/
if (!this->dev_ready) {
udelay(this->chip_delay);
return;
}
}
/*
* Apply this short delay always to ensure that we do wait tWB in
* any case on any machine
*/
ndelay(100);
/* Wait until command is processed */
while (!this->dev_ready(mtd));
}
static void nand_select_chip(struct mtd_info *mtd, int chip)
{
nand_command(mtd, NAND_CMD_RESET, -1, -1);
}
/*
* Main initialization routine
*/
int __init ide_init(void)
{
struct nand_chip *this;
/* Allocate memory for MTD device structure and private data */
ide_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
if (!ide_mtd) {
printk("Unable to allocate IDE NAND MTD structure\n");
return -ENOMEM;
}
/* Get pointer to private data */
this = (struct nand_chip *) (&ide_mtd[1]);
/* Initialize structures */
memset((char *) ide_mtd, 0, sizeof(struct mtd_info));
memset((char *) this, 0, sizeof(struct nand_chip));
/* Link the private data with the MTD structure */
ide_mtd->priv = this;
/* Set address of NAND IO lines */
this->IO_ADDR_R = (void __iomem *) IDE_IO_BASE;
this->IO_ADDR_W = (void __iomem *) IDE_IO_BASE;
/* Set command function for IDE */
this->cmdfunc = nand_command;
/* Set select chip function for IDE */
this->select_chip = nand_select_chip;
/* 20 us command delay time */
this->chip_delay = 20;
/* Set the ECC generator mode */
this->eccmode = NAND_ECC_SOFT;
/* Scan to find existance of the device */
if (nand_scan(ide_mtd, 1)) {
kfree(ide_mtd);
return -ENXIO;
}
/* Register the partitions */
add_mtd_partitions(ide_mtd, partition_info, NUM_PARTITIONS);
/* Return happy */
return 0;
}
module_init(ide_init);
/*
* Clean up routine
*/
#ifdef MODULE
static void __exit ide_cleanup (void)
{
/* Release resources, unregister the device */
nand_release(ide_mtd);
/* Free the MTD device structure */
kfree(ide_mtd);
}
module_exit(ide_cleanup);
#endif
MODULE_LICENSE("GPL");
MODULE_AUTHOR("William J Beksi <wjbeksi@users.sourceforge.net>");
MODULE_DESCRIPTION("Glue layer for NAND flash through an IDE interface");
next reply other threads:[~2004-12-16 13:11 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2004-12-16 13:11 William J Beksi [this message]
2004-12-20 8:09 ` [PATCH] command function for nand flash through IDE Thomas Gleixner
[not found] ` <41C7F8C7.8050607@setabox.com>
2004-12-21 15:27 ` Thomas Gleixner
2004-12-31 4:14 ` William J Beksi
2004-12-31 9:18 ` Thomas Gleixner
2005-01-01 10:50 ` William J Beksi
2005-01-01 10:59 ` Thomas Gleixner
2005-01-01 15:08 ` William J Beksi
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=41C1896F.9000107@setabox.com \
--to=wjbeksi@setabox.com \
--cc=linux-mtd@lists.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.