summaryrefslogtreecommitdiffstats
path: root/target/linux/rb532-2.6/patches/500-Nand.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/rb532-2.6/patches/500-Nand.patch')
-rw-r--r--target/linux/rb532-2.6/patches/500-Nand.patch248
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 0000000000..dc310e9cea
--- /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);
++
++
++
++
++