diff options
Diffstat (limited to 'target/linux/rb532-2.6/patches/500-Nand.patch')
-rw-r--r-- | target/linux/rb532-2.6/patches/500-Nand.patch | 248 |
1 files changed, 248 insertions, 0 deletions
diff --git a/target/linux/rb532-2.6/patches/500-Nand.patch b/target/linux/rb532-2.6/patches/500-Nand.patch new file mode 100644 index 0000000..dc310e9 --- /dev/null +++ b/target/linux/rb532-2.6/patches/500-Nand.patch @@ -0,0 +1,248 @@ +diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig +index cfe288a..c528024 100644 +--- a/drivers/mtd/nand/Kconfig ++++ b/drivers/mtd/nand/Kconfig +@@ -55,6 +55,12 @@ config MTD_NAND_TOTO + help + Support for NAND flash on Texas Instruments Toto platform. + ++config MTD_NAND_RB500 ++ tristate "NAND Flash device on RB500 board" ++ depends on MTD_NAND ++ help ++ Support for NAND flash on RB500 platform. ++ + config MTD_NAND_IDS + tristate + +diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile +index 4174202..2be57c1 100644 +--- a/drivers/mtd/nand/Makefile ++++ b/drivers/mtd/nand/Makefile +@@ -8,6 +8,7 @@ obj-$(CONFIG_MTD_NAND_IDS) += nand_ids. + + obj-$(CONFIG_MTD_NAND_SPIA) += spia.o + obj-$(CONFIG_MTD_NAND_TOTO) += toto.o ++obj-$(CONFIG_MTD_NAND_RB500) += rbmipsnand.o + obj-$(CONFIG_MTD_NAND_AUTCPU12) += autcpu12.o + obj-$(CONFIG_MTD_NAND_EDB7312) += edb7312.o + obj-$(CONFIG_MTD_NAND_AU1550) += au1550nd.o +diff --git a/drivers/mtd/nand/rbmipsnand.c b/drivers/mtd/nand/rbmipsnand.c +new file mode 100644 +index 0000000..6f7452a +--- /dev/null ++++ b/drivers/mtd/nand/rbmipsnand.c +@@ -0,0 +1,211 @@ ++#include <linux/init.h> ++#include <linux/mtd/nand.h> ++#include <linux/mtd/mtd.h> ++#include <linux/mtd/partitions.h> ++#include <linux/delay.h> ++#include <asm/io.h> ++#include <asm/irq.h> ++#include <asm/bootinfo.h> ++//#include <asm/rb/rb100.h> ++ ++#define IDT434_REG_BASE ((volatile void *) KSEG1ADDR(0x18000000)) ++ ++#define SMEM1(x) (*((volatile unsigned char *) (KSEG1ADDR(SMEM1_BASE) + x))) ++ ++#define GPIOF 0x050000 ++#define GPIOC 0x050004 ++#define GPIOD 0x050008 ++ ++#define GPIO_RDY (1 << 0x08) ++#define GPIO_WPX (1 << 0x09) ++#define GPIO_ALE (1 << 0x0a) ++#define GPIO_CLE (1 << 0x0b) ++ ++#define NAND_RW_REG 0x0 //data register ++#define NAND_SET_CEn 0x1 //CE# low ++#define NAND_CLR_CEn 0x2 //CE# high ++#define NAND_CLR_CLE 0x3 //CLE low ++#define NAND_SET_CLE 0x4 //CLE high ++#define NAND_CLR_ALE 0x5 //ALE low ++#define NAND_SET_ALE 0x6 //ALE high ++#define NAND_SET_SPn 0x7 //SP# low (use spare area) ++#define NAND_CLR_SPn 0x8 //SP# high (do not use spare area) ++#define NAND_SET_WPn 0x9 //WP# low ++#define NAND_CLR_WPn 0xA //WP# high ++#define NAND_STS_REG 0xB //Status register ++ ++#define DEV2BASE 0x010020 ++ ++#define LO_WPX (1 << 0) ++#define LO_ALE (1 << 1) ++#define LO_CLE (1 << 2) ++#define LO_CEX (1 << 3) ++#define LO_FOFF (1 << 5) ++#define LO_SPICS (1 << 6) ++#define LO_ULED (1 << 7) ++ ++#define MEM32(x) *((volatile unsigned *) (x)) ++static void __iomem *p_nand; ++ ++extern void changeLatchU5(unsigned char orMask, unsigned char nandMask); ++ ++static int rb500_dev_ready(struct mtd_info *mtd) { ++ return MEM32(IDT434_REG_BASE + GPIOD) & GPIO_RDY; ++} ++/* ++static int rb100_dev_ready(struct mtd_info *mtd) { ++ return SMEM1(NAND_STS_REG) & 0x80; ++} ++*/ ++static unsigned long iflags = 0; ++static int ioff = 0; ++/* ++static void rbmips_hwcontrol400(struct mtd_info *mtd, int cmd) { ++ switch (cmd) { ++ case NAND_CTL_SETCLE: ++ MEM32(IDT434_REG_BASE + GPIOD) |= GPIO_CLE; ++ break; ++ case NAND_CTL_CLRCLE: ++ MEM32(IDT434_REG_BASE + GPIOD) &= ~GPIO_CLE; ++ break; ++ case NAND_CTL_SETALE: ++ MEM32(IDT434_REG_BASE + GPIOD) |= GPIO_ALE; ++ break; ++ case NAND_CTL_CLRALE: ++ MEM32(IDT434_REG_BASE + GPIOD) &= ~GPIO_ALE; ++ break; ++ default: ++ break; ++ } ++} ++*/ ++static void rbmips_hwcontrol500(struct mtd_info *mtd, int cmd) { ++ switch (cmd) { ++ case NAND_CTL_SETCLE: ++ changeLatchU5(LO_CLE, 0); ++ break; ++ case NAND_CTL_CLRCLE: ++ changeLatchU5(0, LO_CLE); ++ break; ++ case NAND_CTL_SETALE: ++ changeLatchU5(LO_ALE, 0); ++ break; ++ case NAND_CTL_CLRALE: ++ changeLatchU5(0, LO_ALE); ++ break; ++ default: ++ break; ++ } ++} ++/* ++static void rbmips_hwcontrol100(struct mtd_info *mtd, int cmd){ ++ switch(cmd){ ++ case NAND_CTL_SETCLE: ++ SMEM1(NAND_SET_CLE) = 0x01; ++ break; ++ case NAND_CTL_CLRCLE: ++ SMEM1(NAND_CLR_CLE) = 0x01; ++ break; ++ case NAND_CTL_SETALE: ++ SMEM1(NAND_SET_ALE) = 0x01; ++ break; ++ case NAND_CTL_CLRALE: ++ SMEM1(NAND_CLR_ALE) = 0x01; ++ break; ++ case NAND_CTL_SETNCE: ++ SMEM1(NAND_SET_CEn) = 0x01; ++ break; ++ case NAND_CTL_CLRNCE: ++ SMEM1(NAND_CLR_CEn) = 0x01; ++ break; ++ } ++} ++*/ ++static struct mtd_partition partition_info[] = { ++ { ++ name: "RouterBoard NAND Boot", ++ offset: 0, ++ size: 4 * 1024 * 1024 ++ }, ++ { ++ name: "RouterBoard NAND Main", ++ offset: MTDPART_OFS_NXTBLK, ++ size: MTDPART_SIZ_FULL ++ } ++}; ++ ++static struct mtd_info rmtd; ++static struct nand_chip rnand; ++ ++static unsigned init_ok = 0; ++ ++unsigned get_rbnand_block_size(void) { ++ if (init_ok) return rmtd.oobblock; else return 0; ++} ++ ++EXPORT_SYMBOL(get_rbnand_block_size); ++ ++int __init rbmips_init(void) { ++ memset(&rmtd, 0, sizeof(rmtd)); ++ memset(&rnand, 0, sizeof(rnand)); ++/* ++ if (is_rb500()) { ++ if (is_rb400()) { ++ printk("RB400 nand\n"); ++ MEM32(IDT434_REG_BASE + GPIOD) |= GPIO_WPX; ++ MEM32(IDT434_REG_BASE + GPIOD) &= ~GPIO_CLE; ++ MEM32(IDT434_REG_BASE + GPIOD) &= ~GPIO_ALE; ++ rnand.hwcontrol = rbmips_hwcontrol400; ++ } else { ++*/ ++ printk("RB500 nand\n"); ++ changeLatchU5(LO_WPX | LO_FOFF | LO_CEX, ++ LO_ULED | LO_ALE | LO_CLE); ++ rnand.hwcontrol = rbmips_hwcontrol500; ++// } ++ ++ rnand.dev_ready = rb500_dev_ready; ++ rnand.IO_ADDR_W = (unsigned char *) ++ KSEG1ADDR(MEM32(IDT434_REG_BASE + DEV2BASE)); ++ rnand.IO_ADDR_R = rnand.IO_ADDR_W; ++/* } else if (is_rb100()) { ++ printk("RB100 nand\n"); ++ MEM32(0xB2000064) = 0x100; ++ MEM32(0xB2000008) = 0x1; ++ SMEM1(NAND_SET_SPn) = 0x01; ++ SMEM1(NAND_CLR_WPn) = 0x01; ++ rnand.IO_ADDR_R = (unsigned char *)KSEG1ADDR(SMEM1_BASE); ++ rnand.IO_ADDR_W = rnand.IO_ADDR_R; ++ rnand.hwcontrol = rbmips_hwcontrol100; ++ rnand.dev_ready = rb100_dev_ready; ++ } ++*/ ++ p_nand = (void __iomem *)ioremap(( void*)0x18a20000, 0x1000); ++ if (!p_nand) { ++ printk("RBnand Unable ioremap buffer"); ++ return -ENXIO; ++ } ++ rnand.eccmode = NAND_ECC_SOFT; ++ rnand.chip_delay = 25; ++ rnand.options |= NAND_NO_AUTOINCR; ++ rmtd.priv = &rnand; ++ ++ int *b = ( int *)KSEG1ADDR( 0x18010020); ++ printk( "dev2base 0x%08x mask 0x%08x c 0x%08x tc 0x%08x\n", b[ 0], b[ 1], b[ 2], b[ 3]); ++ ++ if (nand_scan(&rmtd, 1) && nand_scan(&rmtd, 1) ++ && nand_scan(&rmtd, 1) && nand_scan(&rmtd, 1)) { ++ printk("RBxxx nand device not found"); ++ iounmap ((void *)p_nand); ++ return -ENXIO; ++ } ++ ++ add_mtd_partitions(&rmtd, partition_info, 2); ++ init_ok = 1; ++ return 0; ++} ++ ++module_init(rbmips_init); ++ ++ ++ ++ ++ |