MX31: Add support for NAND to QONG board

The NAND device is connected to the FPGA of the QONG board
and not to the NFC controller. For this reason, the FPGA must
be set and initialized before accessing to the NAND itself.

Signed-off-by: Stefano Babic <sbabic@denx.de>
diff --git a/board/davedenx/qong/qong.c b/board/davedenx/qong/qong.c
index b801150..e73d26b 100644
--- a/board/davedenx/qong/qong.c
+++ b/board/davedenx/qong/qong.c
@@ -25,6 +25,7 @@
 #include <netdev.h>
 #include <asm/arch/mx31.h>
 #include <asm/arch/mx31-regs.h>
+#include <nand.h>
 #include "qong_fpga.h"
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -38,6 +39,15 @@
 	return 0;
 }
 
+static void qong_fpga_reset(void)
+{
+	mx31_gpio_set(QONG_FPGA_RST_PIN, 0);
+	udelay(30);
+	mx31_gpio_set(QONG_FPGA_RST_PIN, 1);
+
+	udelay(300);
+}
+
 int board_init (void)
 {
 	/* Chip selects */
@@ -101,6 +111,15 @@
 	mx31_gpio_mux(IOMUX_MODE(0x91, MUX_CTL_OUT_FUNC | MUX_CTL_IN_GPIO));
 	mx31_gpio_mux(IOMUX_MODE(0x92, MUX_CTL_GPIO));
 	mx31_gpio_mux(IOMUX_MODE(0x93, MUX_CTL_GPIO));
+
+	/* FPGA reset  Pin */
+	/* rstn = 0 */
+	mx31_gpio_set(QONG_FPGA_RST_PIN, 0);
+	mx31_gpio_direction(QONG_FPGA_RST_PIN, MX31_GPIO_DIRECTION_OUT);
+
+	/* set interrupt pin as input */
+	mx31_gpio_direction(QONG_FPGA_IRQ_PIN, MX31_GPIO_DIRECTION_IN);
+
 #endif
 
 	/* setup pins for UART1 */
@@ -127,32 +146,11 @@
 #ifdef CONFIG_QONG_FPGA
 	u32 tmp;
 
-	/* FPGA reset */
-	/* rstn = 0 */
-	tmp = __REG(GPIO2_BASE + GPIO_DR);
-	tmp &= (~(1 << QONG_FPGA_RST_PIN));
-	__REG(GPIO2_BASE + GPIO_DR) = tmp;
-	/* set the GPIO as output */
-	tmp = __REG(GPIO2_BASE + GPIO_GDIR);
-	tmp |= (1 << QONG_FPGA_RST_PIN);
-	__REG(GPIO2_BASE + GPIO_GDIR) = tmp;
-	/* wait */
-	udelay(30);
-	/* rstn = 1 */
-	tmp = __REG(GPIO2_BASE + GPIO_DR);
-	tmp |= (1 << QONG_FPGA_RST_PIN);
-	__REG(GPIO2_BASE + GPIO_DR) = tmp;
-	/* set interrupt pin as input */
-	__REG(GPIO2_BASE + GPIO_GDIR) = tmp | (1 << QONG_FPGA_IRQ_PIN);
-	/* wait while the FPGA starts */
-	udelay(300);
-
 	tmp = *(volatile u32*)QONG_FPGA_CTRL_VERSION;
 	printf("FPGA:  ");
 	printf("version register = %u.%u.%u\n",
 		(tmp & 0xF000) >> 12, (tmp & 0x0F00) >> 8, tmp & 0x00FF);
 #endif
-
 	return 0;
 }
 
@@ -164,3 +162,56 @@
 	return 0;
 #endif
 }
+
+#if defined(CONFIG_QONG_FPGA) && defined(CONFIG_NAND_PLAT)
+static void board_nand_setup(void)
+{
+
+	/* CS3: NAND 8-bit */
+	__REG(CSCR_U(3)) = 0x00004f00;
+	__REG(CSCR_L(3)) = 0x20013b31;
+	__REG(CSCR_A(3)) = 0x00020800;
+	__REG(IOMUXC_GPR) |= 1 << 13;
+
+	mx31_gpio_mux(IOMUX_MODE(MUX_CTL_NFC_WP, MUX_CTL_IN_GPIO));
+	mx31_gpio_mux(IOMUX_MODE(MUX_CTL_NFC_CE, MUX_CTL_IN_GPIO));
+	mx31_gpio_mux(IOMUX_MODE(MUX_CTL_NFC_RB, MUX_CTL_IN_GPIO));
+
+	/* Make sure to reset the fpga else you cannot access NAND */
+	qong_fpga_reset();
+
+	/* Enable NAND flash */
+	mx31_gpio_set(15, 1);
+	mx31_gpio_set(14, 1);
+	mx31_gpio_direction(15, MX31_GPIO_DIRECTION_OUT);
+	mx31_gpio_direction(16, MX31_GPIO_DIRECTION_IN);
+	mx31_gpio_direction(14, MX31_GPIO_DIRECTION_IN);
+	mx31_gpio_set(15, 0);
+
+}
+
+int qong_nand_rdy(void *chip)
+{
+	udelay(1);
+	return mx31_gpio_get(16);
+}
+
+void qong_nand_select_chip(struct mtd_info *mtd, int chip)
+{
+	if (chip >= 0)
+		mx31_gpio_set(15, 0);
+	else
+		mx31_gpio_set(15, 1);
+
+}
+
+void qong_nand_plat_init(void *chip)
+{
+	struct nand_chip *nand = (struct nand_chip *)chip;
+	nand->chip_delay = 20;
+	nand->select_chip = qong_nand_select_chip;
+	nand->options &= ~NAND_BUSWIDTH_16;
+	board_nand_setup();
+}
+
+#endif
diff --git a/board/davedenx/qong/qong_fpga.h b/board/davedenx/qong/qong_fpga.h
index e8042b1..4e11f5a 100644
--- a/board/davedenx/qong/qong_fpga.h
+++ b/board/davedenx/qong/qong_fpga.h
@@ -33,8 +33,8 @@
 #define	QONG_FPGA_TMS_PIN		25
 #define	QONG_FPGA_TDI_PIN		8
 #define	QONG_FPGA_TDO_PIN		7
-#define	QONG_FPGA_RST_PIN		16
-#define	QONG_FPGA_IRQ_PIN		8
+#define	QONG_FPGA_RST_PIN		48
+#define	QONG_FPGA_IRQ_PIN		40
 #endif
 
 #endif /* QONG_FPGA_H */