* [PATCH 0/2] OMAP: Flash device support 3630 sdp board
[not found] <Sukumar Ghorai <s-ghorai@ti.com>
@ 2010-04-06 12:29 ` Sukumar Ghorai
2010-04-06 12:29 ` [PATCH 1/2] OMAP3630SDP: Add support for Flash Sukumar Ghorai
2010-04-13 17:37 ` [PATCH] nand support on omap3 boards Sukumar Ghorai
` (14 subsequent siblings)
15 siblings, 1 reply; 102+ messages in thread
From: Sukumar Ghorai @ 2010-04-06 12:29 UTC (permalink / raw)
To: linux-omap; +Cc: Sukumar Ghorai
Sukumar Ghorai (2):
OMAP3630SDP: Add support for Flash
OMAP3630SDP: enable Flash device support
arch/arm/mach-omap2/Makefile | 1 +
arch/arm/mach-omap2/board-3630sdp.c | 111 +++++++++++++++++++++++++++++++++
arch/arm/mach-omap2/board-sdp-flash.c | 2 +
arch/arm/configs/omap_3630sdp_defconfig | 77 ++++++++++++++++++++++++++++++-
^ permalink raw reply [flat|nested] 102+ messages in thread
* [PATCH 1/2] OMAP3630SDP: Add support for Flash
2010-04-06 12:29 ` [PATCH 0/2] OMAP: Flash device support 3630 sdp board Sukumar Ghorai
@ 2010-04-06 12:29 ` Sukumar Ghorai
2010-04-06 12:29 ` [PATCH 2/2] OMAP3630SDP: enable Flash device support Sukumar Ghorai
2010-04-06 13:02 ` [PATCH 1/2] OMAP3630SDP: Add support for Flash Vimal Singh
0 siblings, 2 replies; 102+ messages in thread
From: Sukumar Ghorai @ 2010-04-06 12:29 UTC (permalink / raw)
To: linux-omap; +Cc: Sukumar Ghorai
Add support for NAND, OneNAND, NOR on OMAP 3630-sdp board.
Signed-off-by: Sukumar Ghorai <s-ghorai@ti.com>
---
---
arch/arm/mach-omap2/Makefile | 1 +
arch/arm/mach-omap2/board-3630sdp.c | 111 +++++++++++++++++++++++++++++++++
arch/arm/mach-omap2/board-sdp-flash.c | 2 +
3 files changed, 114 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index 4b9fc57..0cf463c 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -133,6 +133,7 @@ obj-$(CONFIG_MACH_OMAP_ZOOM3) += board-zoom3.o \
board-zoom-debugboard.o
obj-$(CONFIG_MACH_OMAP_3630SDP) += board-3630sdp.o \
board-zoom-peripherals.o \
+ board-sdp-flash.o \
hsmmc.o
obj-$(CONFIG_MACH_CM_T35) += board-cm-t35.o \
hsmmc.o
diff --git a/arch/arm/mach-omap2/board-3630sdp.c b/arch/arm/mach-omap2/board-3630sdp.c
index 504d2bd..a2ce116 100644
--- a/arch/arm/mach-omap2/board-3630sdp.c
+++ b/arch/arm/mach-omap2/board-3630sdp.c
@@ -22,9 +22,11 @@
#include <plat/usb.h>
#include <mach/board-zoom.h>
+#include <mach/board-sdp.h>
#include "mux.h"
#include "sdram-hynix-h8mbx00u0mer-0em.h"
+extern void sdp_flash_init(struct flash_partitions[]);
#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
@@ -93,12 +95,121 @@ static struct omap_board_mux board_mux[] __initdata = {
#define board_mux NULL
#endif
+static struct mtd_partition sdp_nor_partitions[] = {
+ /* bootloader (U-Boot, etc) in first sector */
+ {
+ .name = "Bootloader-NOR",
+ .offset = 0,
+ .size = SZ_256K,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ /* bootloader params in the next sector */
+ {
+ .name = "Params-NOR",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_256K,
+ .mask_flags = 0,
+ },
+ /* kernel */
+ {
+ .name = "Kernel-NOR",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_2M,
+ .mask_flags = 0
+ },
+ /* file system */
+ {
+ .name = "Filesystem-NOR",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ .mask_flags = 0
+ }
+};
+
+static struct mtd_partition sdp_onenand_partitions[] = {
+ {
+ .name = "X-Loader-OneNAND",
+ .offset = 0,
+ .size = 4 * (64 * 2048),
+ .mask_flags = MTD_WRITEABLE /* force read-only */
+ },
+ {
+ .name = "U-Boot-OneNAND",
+ .offset = MTDPART_OFS_APPEND,
+ .size = 2 * (64 * 2048),
+ .mask_flags = MTD_WRITEABLE /* force read-only */
+ },
+ {
+ .name = "U-Boot Environment-OneNAND",
+ .offset = MTDPART_OFS_APPEND,
+ .size = 1 * (64 * 2048),
+ },
+ {
+ .name = "Kernel-OneNAND",
+ .offset = MTDPART_OFS_APPEND,
+ .size = 16 * (64 * 2048),
+ },
+ {
+ .name = "File System-OneNAND",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ },
+};
+
+static struct mtd_partition sdp_nand_partitions[] = {
+ /* All the partition sizes are listed in terms of NAND block size */
+ {
+ .name = "X-Loader-NAND",
+ .offset = 0,
+ .size = 4 * (64 * 2048),
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ {
+ .name = "U-Boot-NAND",
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x80000 */
+ .size = 10 * (64 * 2048),
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ {
+ .name = "Boot Env-NAND",
+
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x1c0000 */
+ .size = 6 * (64 * 2048),
+ },
+ {
+ .name = "Kernel-NAND",
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x280000 */
+ .size = 40 * (64 * 2048),
+ },
+ {
+ .name = "File System - NAND",
+ .size = MTDPART_SIZ_FULL,
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x780000 */
+ },
+};
+
+static struct flash_partitions sdp_flash_partitions[] = {
+ {
+ .parts = sdp_nor_partitions,
+ .nr_parts = ARRAY_SIZE(sdp_nor_partitions),
+ },
+ {
+ .parts = sdp_onenand_partitions,
+ .nr_parts = ARRAY_SIZE(sdp_onenand_partitions),
+ },
+ {
+ .parts = sdp_nand_partitions,
+ .nr_parts = ARRAY_SIZE(sdp_nand_partitions),
+ },
+};
+
static void __init omap_sdp_init(void)
{
omap3_mux_init(board_mux, OMAP_PACKAGE_CBP);
omap_serial_init();
zoom_peripherals_init();
board_smc91x_init();
+ sdp_flash_init(sdp_flash_partitions);
enable_board_wakeup_source();
usb_ehci_init(&ehci_pdata);
}
diff --git a/arch/arm/mach-omap2/board-sdp-flash.c b/arch/arm/mach-omap2/board-sdp-flash.c
index b1b88de..0604cfb 100644
--- a/arch/arm/mach-omap2/board-sdp-flash.c
+++ b/arch/arm/mach-omap2/board-sdp-flash.c
@@ -161,6 +161,8 @@ __init board_nand_init(struct flash_partitions sdp_nand_parts, u8 cs)
sdp_nand_data.cs = cs;
sdp_nand_data.parts = sdp_nand_parts.parts;
sdp_nand_data.nr_parts = sdp_nand_parts.nr_parts;
+ if (cpu_is_omap3630())
+ sdp_nand_data.devsize = 1; /* 0: 8-bit, 1: 16-bit device */
sdp_nand_data.gpmc_cs_baseaddr = (void *)(OMAP34XX_GPMC_VIRT +
GPMC_CS0_BASE +
--
1.5.4.7
^ permalink raw reply related [flat|nested] 102+ messages in thread
* [PATCH 2/2] OMAP3630SDP: enable Flash device support
2010-04-06 12:29 ` [PATCH 1/2] OMAP3630SDP: Add support for Flash Sukumar Ghorai
@ 2010-04-06 12:29 ` Sukumar Ghorai
2010-04-06 13:02 ` [PATCH 1/2] OMAP3630SDP: Add support for Flash Vimal Singh
1 sibling, 0 replies; 102+ messages in thread
From: Sukumar Ghorai @ 2010-04-06 12:29 UTC (permalink / raw)
To: linux-omap; +Cc: Sukumar Ghorai
update config file to support for NAND, OneNAND, NOR on OMAP 3630-sdp board.
Signed-off-by: Sukumar Ghorai <s-ghorai@ti.com>
---
---
arch/arm/configs/omap_3630sdp_defconfig | 77 ++++++++++++++++++++++++++++++-
1 files changed, 76 insertions(+), 1 deletions(-)
diff --git a/arch/arm/configs/omap_3630sdp_defconfig b/arch/arm/configs/omap_3630sdp_defconfig
index 609f348..a623927 100644
--- a/arch/arm/configs/omap_3630sdp_defconfig
+++ b/arch/arm/configs/omap_3630sdp_defconfig
@@ -461,7 +461,82 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_SYS_HYPERVISOR is not set
CONFIG_CONNECTOR=y
CONFIG_PROC_EVENTS=y
-# CONFIG_MTD is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_TESTS is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_GPIO is not set
+CONFIG_MTD_NAND_OMAP2=y
+CONFIG_MTD_NAND_OMAP_PREFETCH=y
+# CONFIG_MTD_NAND_OMAP_PREFETCH_DMA is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ALAUDA is not set
+CONFIG_MTD_ONENAND=y
+# CONFIG_MTD_ONENAND_VERIFY_WRITE is not set
+# CONFIG_MTD_ONENAND_GENERIC is not set
+CONFIG_MTD_ONENAND_OMAP2=y
+# CONFIG_MTD_ONENAND_OTP is not set
+# CONFIG_MTD_ONENAND_2X_PROGRAM is not set
+# CONFIG_MTD_ONENAND_SIM is not set
# CONFIG_PARPORT is not set
CONFIG_BLK_DEV=y
# CONFIG_BLK_DEV_COW_COMMON is not set
--
1.5.4.7
^ permalink raw reply related [flat|nested] 102+ messages in thread
* Re: [PATCH 1/2] OMAP3630SDP: Add support for Flash
2010-04-06 12:29 ` [PATCH 1/2] OMAP3630SDP: Add support for Flash Sukumar Ghorai
2010-04-06 12:29 ` [PATCH 2/2] OMAP3630SDP: enable Flash device support Sukumar Ghorai
@ 2010-04-06 13:02 ` Vimal Singh
1 sibling, 0 replies; 102+ messages in thread
From: Vimal Singh @ 2010-04-06 13:02 UTC (permalink / raw)
To: Sukumar Ghorai; +Cc: linux-omap
On Tue, Apr 6, 2010 at 5:59 PM, Sukumar Ghorai <s-ghorai@ti.com> wrote:
> Add support for NAND, OneNAND, NOR on OMAP 3630-sdp board.
>
> Signed-off-by: Sukumar Ghorai <s-ghorai@ti.com>
> ---
Feel free to add my acked-by:
Acked-by: Vimal Singh <vimal.newwork@gmail.com>
Regards,
Vimal
^ permalink raw reply [flat|nested] 102+ messages in thread
* [PATCH] nand support on omap3 boards
[not found] <Sukumar Ghorai <s-ghorai@ti.com>
2010-04-06 12:29 ` [PATCH 0/2] OMAP: Flash device support 3630 sdp board Sukumar Ghorai
@ 2010-04-13 17:37 ` Sukumar Ghorai
2010-04-13 17:37 ` [PATCH v3 1/8] omap3: zoom: Introducing 'board-zoom-flash.c' Sukumar Ghorai
` (3 more replies)
2010-04-13 17:44 ` Sukumar Ghorai
` (13 subsequent siblings)
15 siblings, 4 replies; 102+ messages in thread
From: Sukumar Ghorai @ 2010-04-13 17:37 UTC (permalink / raw)
To: linux-omap; +Cc: Sukumar Ghorai
The following set of patches applies on top of the Tony's master branch.
And these are the patches required to enable nand (nor and onenand for sdp
only) for different platform.
Sukumar Ghorai (3):
OMAP: ZOOM: Introducing 'board-zoom-flash.c'
omap3: add support for NAND on zoom2 board
omap3: add support for NAND on zoom3 board
omap-3630-sdp : Add support for Flash
omap-3630-sdp: enable Flash device support
omap3: add support for NAND on LDP board
zoom2: enable NAND support
zoom3: enable NAND support
arch/arm/configs/omap_3630sdp_defconfig | 77 +++++++++++++++++-
arch/arm/configs/omap_zoom2_defconfig | 90 ++++++++++++++++++++-
arch/arm/configs/omap_zoom3_defconfig | 90 ++++++++++++++++++++-
arch/arm/mach-omap2/Makefile | 4 +
arch/arm/mach-omap2/board-3630sdp.c | 110 +++++++++++++++++++++++++
arch/arm/mach-omap2/board-ldp.c | 41 +++++++++
arch/arm/mach-omap2/board-sdp-flash.c | 2 +
arch/arm/mach-omap2/board-zoom-flash.c | 82 ++++++++++++++++++
arch/arm/mach-omap2/board-zoom2.c | 49 +++++++++++
arch/arm/mach-omap2/board-zoom3.c | 48 +++++++++++
arch/arm/mach-omap2/include/mach/board-zoom.h | 11 +++
11 files changed, 601 insertions(+), 3 deletions(-) create mode 100644 arch/arm/mach-omap2/board-zoom-flash.c
^ permalink raw reply [flat|nested] 102+ messages in thread
* [PATCH v3 1/8] omap3: zoom: Introducing 'board-zoom-flash.c'
2010-04-13 17:37 ` [PATCH] nand support on omap3 boards Sukumar Ghorai
@ 2010-04-13 17:37 ` Sukumar Ghorai
2010-04-13 17:37 ` [PATCH v3 2/8] omap3: add support for NAND on zoom2 board Sukumar Ghorai
2010-05-04 6:00 ` Ghorai, Sukumar
` (2 subsequent siblings)
3 siblings, 1 reply; 102+ messages in thread
From: Sukumar Ghorai @ 2010-04-13 17:37 UTC (permalink / raw)
To: linux-omap; +Cc: Sukumar Ghorai, Vimal Singh
This patch adds 'board-zoom-flash.c', which could be utilized by boards similar
to ZOOM2. (For ex: LDP, ZOOM2, ZOOM3). This does initialization for NAND device
based on the 'cs' number and partition information passed from board file
(ex: board-zoom2.c).
Signed-off-by: Vimal Singh <vimalsingh@ti.com>
Signed-off-by: Sukumar Ghorai <s-ghorai@ti.com>
---
arch/arm/mach-omap2/board-zoom-flash.c | 82 +++++++++++++++++++++++++
arch/arm/mach-omap2/include/mach/board-zoom.h | 11 +++
2 files changed, 93 insertions(+), 0 deletions(-)
create mode 100644 arch/arm/mach-omap2/board-zoom-flash.c
diff --git a/arch/arm/mach-omap2/board-zoom-flash.c b/arch/arm/mach-omap2/board-zoom-flash.c
new file mode 100644
index 0000000..55e173b
--- /dev/null
+++ b/arch/arm/mach-omap2/board-zoom-flash.c
@@ -0,0 +1,82 @@
+/*
+ * board-zoom-flash.c
+ *
+ * Copyright (C) 2009 Texas Instruments Inc.
+ * Vimal Singh <vimalsingh@ti.com>
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/nand.h>
+#include <linux/types.h>
+#include <linux/io.h>
+
+#include <asm/mach/flash.h>
+#include <plat/board.h>
+#include <plat/gpmc.h>
+#include <plat/nand.h>
+
+#include <mach/board-zoom.h>
+
+#if defined(CONFIG_MTD_NAND_OMAP2) || defined(CONFIG_MTD_NAND_OMAP2_MODULE)
+
+/* Note that all values in this struct are in nanoseconds */
+static struct gpmc_timings nand_timings = {
+
+ .sync_clk = 0,
+
+ .cs_on = 0,
+ .cs_rd_off = 36,
+ .cs_wr_off = 36,
+
+ .adv_on = 6,
+ .adv_rd_off = 24,
+ .adv_wr_off = 36,
+
+ .we_off = 30,
+ .oe_off = 48,
+
+ .access = 54,
+ .rd_cycle = 72,
+ .wr_cycle = 72,
+
+ .wr_access = 30,
+ .wr_data_mux_bus = 0,
+};
+
+/* NAND chip access: 16 bit */
+static struct omap_nand_platform_data zoom_nand_data = {
+ .nand_setup = NULL,
+ .gpmc_t = &nand_timings,
+ .dma_channel = 3, /* disable DMA in OMAP NAND driver */
+ .dev_ready = NULL,
+ .devsize = 1, /* '0' for 8-bit, '1' for 16-bit device */
+};
+
+/**
+ * zoom_flash_init - Identify devices connected to GPMC and register.
+ *
+ * @return - void.
+ */
+void __init zoom_flash_init(struct flash_partitions zoom_nand_parts[], int cs)
+{
+ u32 gpmc_base_add = OMAP34XX_GPMC_VIRT;
+
+ zoom_nand_data.cs = cs;
+ zoom_nand_data.parts = zoom_nand_parts[0].parts;
+ zoom_nand_data.nr_parts = zoom_nand_parts[0].nr_parts;
+ zoom_nand_data.gpmc_baseaddr = (void *)(gpmc_base_add);
+ zoom_nand_data.gpmc_cs_baseaddr = (void *)(gpmc_base_add +
+ GPMC_CS0_BASE + cs * GPMC_CS_SIZE);
+ gpmc_nand_init(&zoom_nand_data);
+}
+#else
+void __init zoom_flash_init(struct flash_partitions zoom_nand_parts[], int cs)
+{
+}
+#endif /* CONFIG_MTD_NAND_OMAP2 || CONFIG_MTD_NAND_OMAP2_MODULE */
diff --git a/arch/arm/mach-omap2/include/mach/board-zoom.h b/arch/arm/mach-omap2/include/mach/board-zoom.h
index c93b29e..f4469d3 100644
--- a/arch/arm/mach-omap2/include/mach/board-zoom.h
+++ b/arch/arm/mach-omap2/include/mach/board-zoom.h
@@ -1,5 +1,16 @@
/*
* Defines for zoom boards
*/
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+
+struct flash_partitions {
+ struct mtd_partition *parts;
+ int nr_parts;
+};
+
+#define ZOOM_NAND_CS 0
+
+extern void __init zoom_flash_init(struct flash_partitions [], int);
extern int __init zoom_debugboard_init(void);
extern void __init zoom_peripherals_init(void);
--
1.5.4.7
^ permalink raw reply related [flat|nested] 102+ messages in thread
* [PATCH v3 2/8] omap3: add support for NAND on zoom2 board
2010-04-13 17:37 ` [PATCH v3 1/8] omap3: zoom: Introducing 'board-zoom-flash.c' Sukumar Ghorai
@ 2010-04-13 17:37 ` Sukumar Ghorai
2010-04-13 17:37 ` [PATCH v3 3/8] omap3: add support for NAND on zoom3 board Sukumar Ghorai
0 siblings, 1 reply; 102+ messages in thread
From: Sukumar Ghorai @ 2010-04-13 17:37 UTC (permalink / raw)
To: linux-omap; +Cc: Sukumar Ghorai, Vimal Singh
This patch adds NAND support to ZOOM2 board.
This uses 'board-zoom-flash.c' for NAND initialization.
Signed-off-by: Sukumar Ghorai <s-ghorai@ti.com>
Signed-off-by: Vimal Singh <vimalsingh@ti.com>
---
arch/arm/mach-omap2/Makefile | 1 +
arch/arm/mach-omap2/board-zoom2.c | 49 +++++++++++++++++++++++++++++++++++++
2 files changed, 50 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index 4b9fc57..f8d9a42 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -124,6 +124,7 @@ obj-$(CONFIG_MACH_NOKIA_RX51) += board-rx51.o \
board-rx51-peripherals.o \
hsmmc.o
obj-$(CONFIG_MACH_OMAP_ZOOM2) += board-zoom2.o \
+ board-zoom-flash.o \
board-zoom-peripherals.o \
hsmmc.o \
board-zoom-debugboard.o
diff --git a/arch/arm/mach-omap2/board-zoom2.c b/arch/arm/mach-omap2/board-zoom2.c
index 9a26f84..e0f4901 100644
--- a/arch/arm/mach-omap2/board-zoom2.c
+++ b/arch/arm/mach-omap2/board-zoom2.c
@@ -77,10 +77,59 @@ static struct omap_board_mux board_mux[] __initdata = {
#define board_mux NULL
#endif
+static struct mtd_partition zoom_nand_partitions[] = {
+ /* All the partition sizes are listed in terms of NAND block size */
+ {
+ .name = "X-Loader-NAND",
+ .offset = 0,
+ .size = 4 * (64 * 2048), /* 512KB, 0x80000 */
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ {
+ .name = "U-Boot-NAND",
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x80000 */
+ .size = 10 * (64 * 2048), /* 1.25MB, 0x140000 */
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ {
+ .name = "Boot Env-NAND",
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x1c0000 */
+ .size = 2 * (64 * 2048), /* 256KB, 0x40000 */
+ },
+ {
+ .name = "Kernel-NAND",
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x0200000*/
+ .size = 240 * (64 * 2048), /* 30M, 0x1E00000 */
+ },
+ {
+ .name = "system",
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x2000000 */
+ .size = 3328 * (64 * 2048), /* 416M, 0x1A000000 */
+ },
+ {
+ .name = "userdata",
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x1C000000*/
+ .size = 256 * (64 * 2048), /* 32M, 0x2000000 */
+ },
+ {
+ .name = "cache",
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x1E000000*/
+ .size = 256 * (64 * 2048), /* 32M, 0x2000000 */
+ },
+};
+
+static struct flash_partitions zoom_flash_partitions[] = {
+ {
+ .parts = zoom_nand_partitions,
+ .nr_parts = ARRAY_SIZE(zoom_nand_partitions),
+ },
+};
+
static void __init omap_zoom2_init(void)
{
omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
zoom_peripherals_init();
+ zoom_flash_init(zoom_flash_partitions, ZOOM_NAND_CS);
zoom_debugboard_init();
}
^ permalink raw reply related [flat|nested] 102+ messages in thread
* [PATCH v3 3/8] omap3: add support for NAND on zoom3 board
2010-04-13 17:37 ` [PATCH v3 2/8] omap3: add support for NAND on zoom2 board Sukumar Ghorai
@ 2010-04-13 17:37 ` Sukumar Ghorai
2010-04-13 17:37 ` [PATCH v2 4/8] omap-3630-sdp : Add support for Flash Sukumar Ghorai
0 siblings, 1 reply; 102+ messages in thread
From: Sukumar Ghorai @ 2010-04-13 17:37 UTC (permalink / raw)
To: linux-omap; +Cc: Sukumar Ghorai, Vimal Singh
patch adds NAND support to zoom3 board.
Signed-off-by: SUkumar Ghorai <s-ghorai@ti.com>
Signed-off-by: Vimal Singh <vimalsingh@ti.com>
---
arch/arm/mach-omap2/Makefile | 1 +
arch/arm/mach-omap2/board-zoom3.c | 48 +++++++++++++++++++++++++++++++++++++
2 files changed, 49 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index f8d9a42..57f418b 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -129,6 +129,7 @@ obj-$(CONFIG_MACH_OMAP_ZOOM2) += board-zoom2.o \
hsmmc.o \
board-zoom-debugboard.o
obj-$(CONFIG_MACH_OMAP_ZOOM3) += board-zoom3.o \
+ board-zoom-flash.o \
board-zoom-peripherals.o \
hsmmc.o \
board-zoom-debugboard.o
diff --git a/arch/arm/mach-omap2/board-zoom3.c b/arch/arm/mach-omap2/board-zoom3.c
index cd3e40c..8a9811e 100644
--- a/arch/arm/mach-omap2/board-zoom3.c
+++ b/arch/arm/mach-omap2/board-zoom3.c
@@ -34,6 +34,53 @@ static void __init omap_zoom_map_io(void)
static struct omap_board_config_kernel zoom_config[] __initdata = {
};
+static struct mtd_partition zoom_nand_partitions[] = {
+ /* All the partition sizes are listed in terms of NAND block size */
+ {
+ .name = "X-Loader-NAND",
+ .offset = 0,
+ .size = 4 * (64 * 2048), /* 512KB, 0x80000 */
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ {
+ .name = "U-Boot-NAND",
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x80000 */
+ .size = 10 * (64 * 2048), /* 1.25MB, 0x140000 */
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ {
+ .name = "Boot Env-NAND",
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x1c0000 */
+ .size = 2 * (64 * 2048), /* 256KB, 0x40000 */
+ },
+ {
+ .name = "Kernel-NAND",
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x0200000*/
+ .size = 240 * (64 * 2048), /* 30M, 0x1E00000 */
+ },
+ {
+ .name = "system",
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x2000000 */
+ .size = 3328 * (64 * 2048), /* 416M, 0x1A000000 */
+ },
+ {
+ .name = "userdata",
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x1C000000*/
+ .size = 256 * (64 * 2048), /* 32M, 0x2000000 */
+ },
+ {
+ .name = "cache",
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x1E000000*/
+ .size = 256 * (64 * 2048), /* 32M, 0x2000000 */
+ },
+};
+
+static struct flash_partitions zoom_flash_partitions[] = {
+ {
+ .parts = zoom_nand_partitions,
+ .nr_parts = ARRAY_SIZE(zoom_nand_partitions),
+ },
+};
static void __init omap_zoom_init_irq(void)
{
omap_board_config = zoom_config;
@@ -66,6 +113,7 @@ static void __init omap_zoom_init(void)
{
omap3_mux_init(board_mux, OMAP_PACKAGE_CBP);
zoom_peripherals_init();
+ zoom_flash_init(zoom_flash_partitions, ZOOM_NAND_CS);
zoom_debugboard_init();
omap_mux_init_gpio(64, OMAP_PIN_OUTPUT);
^ permalink raw reply related [flat|nested] 102+ messages in thread
* [PATCH v2 4/8] omap-3630-sdp : Add support for Flash
2010-04-13 17:37 ` [PATCH v3 3/8] omap3: add support for NAND on zoom3 board Sukumar Ghorai
@ 2010-04-13 17:37 ` Sukumar Ghorai
2010-04-13 17:37 ` [PATCH v2 5/8] omap-3630-sdp: enable Flash device support Sukumar Ghorai
0 siblings, 1 reply; 102+ messages in thread
From: Sukumar Ghorai @ 2010-04-13 17:37 UTC (permalink / raw)
To: linux-omap; +Cc: Sukumar Ghorai
add support for NAND, OneNAND, NOR on omap 3630-sdp board.
Signed-off-by: Sukumar Ghorai <s-ghorai@ti.com>
---
arch/arm/mach-omap2/Makefile | 1 +
arch/arm/mach-omap2/board-3630sdp.c | 110 +++++++++++++++++++++++++++++++++
arch/arm/mach-omap2/board-sdp-flash.c | 2 +
3 files changed, 113 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index 57f418b..0b0481d
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -135,6 +135,7 @@ obj-$(CONFIG_MACH_OMAP_ZOOM3) += board-zoom3.o \
board-zoom-debugboard.o
obj-$(CONFIG_MACH_OMAP_3630SDP) += board-3630sdp.o \
board-zoom-peripherals.o \
+ board-sdp-flash.o \
hsmmc.o
obj-$(CONFIG_MACH_CM_T35) += board-cm-t35.o \
hsmmc.o
diff --git a/arch/arm/mach-omap2/board-3630sdp.c b/arch/arm/mach-omap2/board-3630sdp.c
index 504d2bd..0919dca
--- a/arch/arm/mach-omap2/board-3630sdp.c
+++ b/arch/arm/mach-omap2/board-3630sdp.c
@@ -25,6 +25,7 @@
#include "mux.h"
#include "sdram-hynix-h8mbx00u0mer-0em.h"
+extern void sdp_flash_init(struct flash_partitions[]);
#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
@@ -93,12 +94,121 @@ static struct omap_board_mux board_mux[] __initdata = {
#define board_mux NULL
#endif
+static struct mtd_partition sdp_nor_partitions[] = {
+ /* bootloader (U-Boot, etc) in first sector */
+ {
+ .name = "Bootloader-NOR",
+ .offset = 0,
+ .size = SZ_256K,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ /* bootloader params in the next sector */
+ {
+ .name = "Params-NOR",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_256K,
+ .mask_flags = 0,
+ },
+ /* kernel */
+ {
+ .name = "Kernel-NOR",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_2M,
+ .mask_flags = 0
+ },
+ /* file system */
+ {
+ .name = "Filesystem-NOR",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ .mask_flags = 0
+ }
+};
+
+static struct mtd_partition sdp_onenand_partitions[] = {
+ {
+ .name = "X-Loader-OneNAND",
+ .offset = 0,
+ .size = 4 * (64 * 2048),
+ .mask_flags = MTD_WRITEABLE /* force read-only */
+ },
+ {
+ .name = "U-Boot-OneNAND",
+ .offset = MTDPART_OFS_APPEND,
+ .size = 2 * (64 * 2048),
+ .mask_flags = MTD_WRITEABLE /* force read-only */
+ },
+ {
+ .name = "U-Boot Environment-OneNAND",
+ .offset = MTDPART_OFS_APPEND,
+ .size = 1 * (64 * 2048),
+ },
+ {
+ .name = "Kernel-OneNAND",
+ .offset = MTDPART_OFS_APPEND,
+ .size = 16 * (64 * 2048),
+ },
+ {
+ .name = "File System-OneNAND",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ },
+};
+
+static struct mtd_partition sdp_nand_partitions[] = {
+ /* All the partition sizes are listed in terms of NAND block size */
+ {
+ .name = "X-Loader-NAND",
+ .offset = 0,
+ .size = 4 * (64 * 2048),
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ {
+ .name = "U-Boot-NAND",
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x80000 */
+ .size = 10 * (64 * 2048),
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ {
+ .name = "Boot Env-NAND",
+
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x1c0000 */
+ .size = 6 * (64 * 2048),
+ },
+ {
+ .name = "Kernel-NAND",
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x280000 */
+ .size = 40 * (64 * 2048),
+ },
+ {
+ .name = "File System - NAND",
+ .size = MTDPART_SIZ_FULL,
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x780000 */
+ },
+};
+
+static struct flash_partitions sdp_flash_partitions[] = {
+ {
+ .parts = sdp_nor_partitions,
+ .nr_parts = ARRAY_SIZE(sdp_nor_partitions),
+ },
+ {
+ .parts = sdp_onenand_partitions,
+ .nr_parts = ARRAY_SIZE(sdp_onenand_partitions),
+ },
+ {
+ .parts = sdp_nand_partitions,
+ .nr_parts = ARRAY_SIZE(sdp_nand_partitions),
+ },
+};
+
static void __init omap_sdp_init(void)
{
omap3_mux_init(board_mux, OMAP_PACKAGE_CBP);
omap_serial_init();
zoom_peripherals_init();
board_smc91x_init();
+ sdp_flash_init(sdp_flash_partitions);
enable_board_wakeup_source();
usb_ehci_init(&ehci_pdata);
}
diff --git a/arch/arm/mach-omap2/board-sdp-flash.c b/arch/arm/mach-omap2/board-sdp-flash.c
index b1b88de..0604cfb 100644
--- a/arch/arm/mach-omap2/board-sdp-flash.c
+++ b/arch/arm/mach-omap2/board-sdp-flash.c
@@ -161,6 +161,8 @@ __init board_nand_init(struct flash_partitions sdp_nand_parts, u8 cs)
sdp_nand_data.cs = cs;
sdp_nand_data.parts = sdp_nand_parts.parts;
sdp_nand_data.nr_parts = sdp_nand_parts.nr_parts;
+ if (cpu_is_omap3630())
+ sdp_nand_data.devsize = 1; /* 0: 8-bit, 1: 16-bit device */
sdp_nand_data.gpmc_cs_baseaddr = (void *)(OMAP34XX_GPMC_VIRT +
GPMC_CS0_BASE +
^ permalink raw reply related [flat|nested] 102+ messages in thread
* [PATCH v2 5/8] omap-3630-sdp: enable Flash device support
2010-04-13 17:37 ` [PATCH v2 4/8] omap-3630-sdp : Add support for Flash Sukumar Ghorai
@ 2010-04-13 17:37 ` Sukumar Ghorai
2010-04-13 17:37 ` [PATCH v2 6/8] omap3: add support for NAND on LDP board Sukumar Ghorai
0 siblings, 1 reply; 102+ messages in thread
From: Sukumar Ghorai @ 2010-04-13 17:37 UTC (permalink / raw)
To: linux-omap; +Cc: Sukumar Ghorai
update config file to support for NAND, OneNAND, NOR on omap 3630-sdp board.
Signed-off-by: Sukumar Ghorai <s-ghorai@ti.com>
---
arch/arm/configs/omap_3630sdp_defconfig | 77 ++++++++++++++++++++++++++++++-
1 files changed, 76 insertions(+), 1 deletions(-)
diff --git a/arch/arm/configs/omap_3630sdp_defconfig b/arch/arm/configs/omap_3630sdp_defconfig
index 609f348..a623927 100644
--- a/arch/arm/configs/omap_3630sdp_defconfig
+++ b/arch/arm/configs/omap_3630sdp_defconfig
@@ -461,7 +461,82 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_SYS_HYPERVISOR is not set
CONFIG_CONNECTOR=y
CONFIG_PROC_EVENTS=y
-# CONFIG_MTD is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_TESTS is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_GPIO is not set
+CONFIG_MTD_NAND_OMAP2=y
+CONFIG_MTD_NAND_OMAP_PREFETCH=y
+# CONFIG_MTD_NAND_OMAP_PREFETCH_DMA is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ALAUDA is not set
+CONFIG_MTD_ONENAND=y
+# CONFIG_MTD_ONENAND_VERIFY_WRITE is not set
+# CONFIG_MTD_ONENAND_GENERIC is not set
+CONFIG_MTD_ONENAND_OMAP2=y
+# CONFIG_MTD_ONENAND_OTP is not set
+# CONFIG_MTD_ONENAND_2X_PROGRAM is not set
+# CONFIG_MTD_ONENAND_SIM is not set
# CONFIG_PARPORT is not set
CONFIG_BLK_DEV=y
# CONFIG_BLK_DEV_COW_COMMON is not set
--
1.5.4.7
^ permalink raw reply related [flat|nested] 102+ messages in thread
* [PATCH v2 6/8] omap3: add support for NAND on LDP board
2010-04-13 17:37 ` [PATCH v2 5/8] omap-3630-sdp: enable Flash device support Sukumar Ghorai
@ 2010-04-13 17:37 ` Sukumar Ghorai
2010-04-13 17:37 ` [PATCH 7/8] zoom2: enable NAND support Sukumar Ghorai
0 siblings, 1 reply; 102+ messages in thread
From: Sukumar Ghorai @ 2010-04-13 17:37 UTC (permalink / raw)
To: linux-omap; +Cc: Sukumar Ghorai, Vimal Singh
patch adds NAND support to LDP board.
Signed-off-by: Vimal Singh <vimalsingh@ti.com>
Signed-off-by: Sukumar Ghorai <s-ghorai@ti.com>
---
arch/arm/mach-omap2/Makefile | 1 +
arch/arm/mach-omap2/board-ldp.c | 41 +++++++++++++++++++++++++++++++++++++++
2 files changed, 42 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index 0cf463c..7556e72
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -108,6 +108,7 @@ obj-$(CONFIG_MACH_OMAP3_BEAGLE) += board-omap3beagle.o \
obj-$(CONFIG_MACH_DEVKIT8000) += board-devkit8000.o \
hsmmc.o
obj-$(CONFIG_MACH_OMAP_LDP) += board-ldp.o \
+ board-zoom-flash.o \
hsmmc.o
obj-$(CONFIG_MACH_OVERO) += board-overo.o \
hsmmc.o
diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c
index 5fcb52e..0976bd9 100644
--- a/arch/arm/mach-omap2/board-ldp.c
+++ b/arch/arm/mach-omap2/board-ldp.c
@@ -38,6 +38,7 @@
#include <plat/board.h>
#include <plat/common.h>
#include <plat/gpmc.h>
+#include <mach/board-zoom.h>
#include <asm/delay.h>
#include <plat/control.h>
@@ -389,6 +390,45 @@ static struct omap_musb_board_data musb_board_data = {
.power = 100,
};
+static struct mtd_partition zoom_nand_partitions[] = {
+ /* All the partition sizes are listed in terms of NAND block size */
+ {
+ .name = "X-Loader-NAND",
+ .offset = 0,
+ .size = 4 * (64 * 2048), /* 512KB, 0x80000 */
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ {
+ .name = "U-Boot-NAND",
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x80000 */
+ .size = 10 * (64 * 2048), /* 1.25MB, 0x140000 */
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ {
+ .name = "Boot Env-NAND",
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x1c0000 */
+ .size = 2 * (64 * 2048), /* 256KB, 0x40000 */
+ },
+ {
+ .name = "Kernel-NAND",
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x0200000*/
+ .size = 240 * (64 * 2048), /* 30M, 0x1E00000 */
+ },
+ {
+ .name = "File System - NAND",
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x2000000 */
+ .size = MTDPART_SIZ_FULL, /* 96MB, 0x6000000 */
+ },
+
+};
+
+static struct flash_partitions zoom_flash_partitions[] = {
+ {
+ .parts = zoom_nand_partitions,
+ .nr_parts = ARRAY_SIZE(zoom_nand_partitions),
+ },
+};
+
static void __init omap_ldp_init(void)
{
omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
@@ -401,6 +441,7 @@ static void __init omap_ldp_init(void)
ads7846_dev_init();
omap_serial_init();
usb_musb_init(&musb_board_data);
+ zoom_flash_init(zoom_flash_partitions, ZOOM_NAND_CS);
omap2_hsmmc_init(mmc);
/* link regulators to MMC adapters */
--
1.5.4.7
^ permalink raw reply related [flat|nested] 102+ messages in thread
* [PATCH 7/8] zoom2: enable NAND support
2010-04-13 17:37 ` [PATCH v2 6/8] omap3: add support for NAND on LDP board Sukumar Ghorai
@ 2010-04-13 17:37 ` Sukumar Ghorai
2010-04-13 17:37 ` [PATCH 8/8] zoom3: " Sukumar Ghorai
0 siblings, 1 reply; 102+ messages in thread
From: Sukumar Ghorai @ 2010-04-13 17:37 UTC (permalink / raw)
To: linux-omap; +Cc: Sukumar Ghorai
update config file to support for NAND in zoom2.
Signed-off-by: Sukumar Ghorai <s-ghorai@ti.com>
---
arch/arm/configs/omap_zoom2_defconfig | 90 ++++++++++++++++++++++++++++++++-
1 files changed, 89 insertions(+), 1 deletions(-)
diff --git a/arch/arm/configs/omap_zoom2_defconfig b/arch/arm/configs/omap_zoom2_defconfig
old mode 100644
new mode 100755
index 881faea..29f6f71
--- a/arch/arm/configs/omap_zoom2_defconfig
+++ b/arch/arm/configs/omap_zoom2_defconfig
@@ -440,7 +440,95 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_SYS_HYPERVISOR is not set
CONFIG_CONNECTOR=y
CONFIG_PROC_EVENTS=y
-# CONFIG_MTD is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_TESTS is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SST25L is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_GPIO is not set
+CONFIG_MTD_NAND_OMAP2=y
+CONFIG_MTD_NAND_OMAP_PREFETCH=y
+# CONFIG_MTD_NAND_OMAP_PREFETCH_DMA is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ALAUDA is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
# CONFIG_PARPORT is not set
CONFIG_BLK_DEV=y
# CONFIG_BLK_DEV_COW_COMMON is not set
--
1.5.4.7
^ permalink raw reply related [flat|nested] 102+ messages in thread
* [PATCH 8/8] zoom3: enable NAND support
2010-04-13 17:37 ` [PATCH 7/8] zoom2: enable NAND support Sukumar Ghorai
@ 2010-04-13 17:37 ` Sukumar Ghorai
2010-04-13 17:37 ` [PATCH] nand support on omap3 boards Sukumar Ghorai
0 siblings, 1 reply; 102+ messages in thread
From: Sukumar Ghorai @ 2010-04-13 17:37 UTC (permalink / raw)
To: linux-omap; +Cc: Sukumar Ghorai
update config file to support for NAND on zoom3 board.
Signed-off-by: Sukumar Ghorai <s-ghorai@ti.com>
---
arch/arm/configs/omap_zoom3_defconfig | 90 ++++++++++++++++++++++++++++++++-
1 files changed, 89 insertions(+), 1 deletions(-)
diff --git a/arch/arm/configs/omap_zoom3_defconfig b/arch/arm/configs/omap_zoom3_defconfig
index 5e55b55..1a12e3e
--- a/arch/arm/configs/omap_zoom3_defconfig
+++ b/arch/arm/configs/omap_zoom3_defconfig
@@ -461,7 +461,95 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_SYS_HYPERVISOR is not set
CONFIG_CONNECTOR=y
CONFIG_PROC_EVENTS=y
-# CONFIG_MTD is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_TESTS is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SST25L is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_GPIO is not set
+CONFIG_MTD_NAND_OMAP2=y
+CONFIG_MTD_NAND_OMAP_PREFETCH=y
+# CONFIG_MTD_NAND_OMAP_PREFETCH_DMA is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ALAUDA is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
# CONFIG_PARPORT is not set
CONFIG_BLK_DEV=y
# CONFIG_BLK_DEV_COW_COMMON is not set
--
1.5.4.7
^ permalink raw reply related [flat|nested] 102+ messages in thread
* [PATCH] nand support on omap3 boards
2010-04-13 17:37 ` [PATCH 8/8] zoom3: " Sukumar Ghorai
@ 2010-04-13 17:37 ` Sukumar Ghorai
2010-04-13 17:37 ` [PATCH 8/8] omap3: GPMC register definition at common location Sukumar Ghorai
2010-04-14 4:35 ` [PATCH] nand support on omap3 boards Vimal Singh
0 siblings, 2 replies; 102+ messages in thread
From: Sukumar Ghorai @ 2010-04-13 17:37 UTC (permalink / raw)
To: linux-omap; +Cc: Sukumar Ghorai
The following set of patches applies on top of the Tony's master branch.
And dependency on following series of patch -
Sukumar Ghorai (3):
omap3: GPMC register definition at common location
omap3: NAND Prefetch in IRQ mode support
omap-3630 NAND: enable NAND io in prefetch-irq mode
omap: NAND: ecc layout select from board file
omap: NAND: Making ecc layout as compatible with romcode ecc
^ permalink raw reply [flat|nested] 102+ messages in thread
* [PATCH 8/8] omap3: GPMC register definition at common location
2010-04-13 17:37 ` [PATCH] nand support on omap3 boards Sukumar Ghorai
@ 2010-04-13 17:37 ` Sukumar Ghorai
2010-04-13 17:37 ` [PATCH] omap3: NAND Prefetch in IRQ mode support Sukumar Ghorai
2010-04-14 4:35 ` [PATCH] nand support on omap3 boards Vimal Singh
1 sibling, 1 reply; 102+ messages in thread
From: Sukumar Ghorai @ 2010-04-13 17:37 UTC (permalink / raw)
To: linux-omap; +Cc: Sukumar Ghorai, Vimal Singh
GPMC register definition move to common place in gpmc.h.
Signed-off-by: Sukumar Ghorai <s-ghorai@ti.com>
Signed-off-by: Vimal Singh <vimalsingh@ti.com>
---
arch/arm/mach-omap2/gpmc.c | 38 +------------------------------
arch/arm/plat-omap/include/plat/gpmc.h | 36 +++++++++++++++++++++++++++--
drivers/mtd/nand/omap2.c | 14 ++++-------
3 files changed, 40 insertions(+), 48 deletions(-)
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index 5bc3ca0..9c77af0 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -28,40 +28,6 @@
#include <plat/sdrc.h>
-/* GPMC register offsets */
-#define GPMC_REVISION 0x00
-#define GPMC_SYSCONFIG 0x10
-#define GPMC_SYSSTATUS 0x14
-#define GPMC_IRQSTATUS 0x18
-#define GPMC_IRQENABLE 0x1c
-#define GPMC_TIMEOUT_CONTROL 0x40
-#define GPMC_ERR_ADDRESS 0x44
-#define GPMC_ERR_TYPE 0x48
-#define GPMC_CONFIG 0x50
-#define GPMC_STATUS 0x54
-#define GPMC_PREFETCH_CONFIG1 0x1e0
-#define GPMC_PREFETCH_CONFIG2 0x1e4
-#define GPMC_PREFETCH_CONTROL 0x1ec
-#define GPMC_PREFETCH_STATUS 0x1f0
-#define GPMC_ECC_CONFIG 0x1f4
-#define GPMC_ECC_CONTROL 0x1f8
-#define GPMC_ECC_SIZE_CONFIG 0x1fc
-
-#define GPMC_CS0 0x60
-#define GPMC_CS_SIZE 0x30
-
-#define GPMC_MEM_START 0x00000000
-#define GPMC_MEM_END 0x3FFFFFFF
-#define BOOT_ROM_SPACE 0x100000 /* 1MB */
-
-#define GPMC_CHUNK_SHIFT 24 /* 16 MB */
-#define GPMC_SECTION_SHIFT 28 /* 128 MB */
-
-#define PREFETCH_FIFOTHRESHOLD (0x40 << 8)
-#define CS_NUM_SHIFT 24
-#define ENABLE_PREFETCH (0x1 << 7)
-#define DMA_MPU_MODE 2
-
/* Structure to save gpmc cs context */
struct gpmc_cs_config {
u32 config1;
@@ -112,7 +78,7 @@ void gpmc_cs_write_reg(int cs, int idx, u32 val)
{
void __iomem *reg_addr;
- reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx;
+ reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx;
__raw_writel(val, reg_addr);
}
@@ -120,7 +86,7 @@ u32 gpmc_cs_read_reg(int cs, int idx)
{
void __iomem *reg_addr;
- reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx;
+ reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx;
return __raw_readl(reg_addr);
}
diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h
index 145838a..347d212 100644
--- a/arch/arm/plat-omap/include/plat/gpmc.h
+++ b/arch/arm/plat-omap/include/plat/gpmc.h
@@ -25,10 +25,40 @@
#define GPMC_CS_NAND_ADDRESS 0x20
#define GPMC_CS_NAND_DATA 0x24
-#define GPMC_CONFIG 0x50
-#define GPMC_STATUS 0x54
+/* GPMC register offsets */
+#define GPMC_REVISION 0x00
+#define GPMC_SYSCONFIG 0x10
+#define GPMC_SYSSTATUS 0x14
+#define GPMC_IRQSTATUS 0x18
+#define GPMC_IRQENABLE 0x1c
+#define GPMC_TIMEOUT_CONTROL 0x40
+#define GPMC_ERR_ADDRESS 0x44
+#define GPMC_ERR_TYPE 0x48
+#define GPMC_CONFIG 0x50
+#define GPMC_STATUS 0x54
+#define GPMC_PREFETCH_CONFIG1 0x1e0
+#define GPMC_PREFETCH_CONFIG2 0x1e4
+#define GPMC_PREFETCH_CONTROL 0x1ec
+#define GPMC_PREFETCH_STATUS 0x1f0
+#define GPMC_ECC_CONFIG 0x1f4
+#define GPMC_ECC_CONTROL 0x1f8
+#define GPMC_ECC_SIZE_CONFIG 0x1fc
+#define GPMC_ECC1_RESULT 0x200
+
#define GPMC_CS0_BASE 0x60
-#define GPMC_CS_SIZE 0x30
+#define GPMC_CS_SIZE 0x30
+
+#define GPMC_MEM_START 0x00000000
+#define GPMC_MEM_END 0x3FFFFFFF
+#define BOOT_ROM_SPACE 0x100000 /* 1MB */
+
+#define GPMC_CHUNK_SHIFT 24 /* 16 MB */
+#define GPMC_SECTION_SHIFT 28 /* 128 MB */
+
+#define PREFETCH_FIFOTHRESHOLD (0x40 << 8)
+#define CS_NUM_SHIFT 24
+#define ENABLE_PREFETCH (0x1 << 7)
+#define DMA_MPU_MODE 2
#define GPMC_CONFIG1_WRAPBURST_SUPP (1 << 31)
#define GPMC_CONFIG1_READMULTIPLE_SUPP (1 << 30)
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 26aec00..ceb3877 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -22,12 +22,6 @@
#include <plat/gpmc.h>
#include <plat/nand.h>
-#define GPMC_IRQ_STATUS 0x18
-#define GPMC_ECC_CONFIG 0x1F4
-#define GPMC_ECC_CONTROL 0x1F8
-#define GPMC_ECC_SIZE_CONFIG 0x1FC
-#define GPMC_ECC1_RESULT 0x200
-
#define DRIVER_NAME "omap2-nand"
#define NAND_WP_OFF 0
@@ -36,6 +30,7 @@
#define GPMC_BUF_FULL 0x00000001
#define GPMC_BUF_EMPTY 0x00000000
+#ifdef CONFIG_MTD_NAND_OMAP_HWECC
#define NAND_Ecc_P1e (1 << 0)
#define NAND_Ecc_P2e (1 << 1)
#define NAND_Ecc_P4e (1 << 2)
@@ -102,6 +97,7 @@
#define P4e_s(a) (TF(a & NAND_Ecc_P4e) << 0)
#define P4o_s(a) (TF(a & NAND_Ecc_P4o) << 1)
+#endif /* CONFIG_MTD_NAND_OMAP_HWECC */
#ifdef CONFIG_MTD_PARTITIONS
static const char *part_probes[] = { "cmdlinepart", NULL };
@@ -853,20 +849,20 @@ static int omap_dev_ready(struct mtd_info *mtd)
{
struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
mtd);
- unsigned int val = __raw_readl(info->gpmc_baseaddr + GPMC_IRQ_STATUS);
+ unsigned int val = __raw_readl(info->gpmc_baseaddr + GPMC_IRQSTATUS);
if ((val & 0x100) == 0x100) {
/* Clear IRQ Interrupt */
val |= 0x100;
val &= ~(0x0);
- __raw_writel(val, info->gpmc_baseaddr + GPMC_IRQ_STATUS);
+ __raw_writel(val, info->gpmc_baseaddr + GPMC_IRQSTATUS);
} else {
unsigned int cnt = 0;
while (cnt++ < 0x1FF) {
if ((val & 0x100) == 0x100)
return 0;
val = __raw_readl(info->gpmc_baseaddr +
- GPMC_IRQ_STATUS);
+ GPMC_IRQSTATUS);
}
}
^ permalink raw reply related [flat|nested] 102+ messages in thread
* [PATCH] omap3: NAND Prefetch in IRQ mode support
2010-04-13 17:37 ` [PATCH 8/8] omap3: GPMC register definition at common location Sukumar Ghorai
@ 2010-04-13 17:37 ` Sukumar Ghorai
2010-04-13 17:37 ` [PATCH] omap-3630 NAND: enable NAND io in prefetch-irq mode Sukumar Ghorai
0 siblings, 1 reply; 102+ messages in thread
From: Sukumar Ghorai @ 2010-04-13 17:37 UTC (permalink / raw)
To: linux-omap; +Cc: Sukumar Ghorai, Vimal Singh
This patch enable prefetch-irq mode for NAND.
Signed-off-by: Vimal Singh <vimalsingh@ti.com>
Signed-off-by: Sukumar Ghorai <s-ghorai@ti.com>
---
arch/arm/mach-omap2/board-sdp-flash.c | 1 +
arch/arm/mach-omap2/board-zoom-flash.c | 1 +
arch/arm/plat-omap/include/plat/nand.h | 1 +
drivers/mtd/nand/Kconfig | 14 ++-
drivers/mtd/nand/omap2.c | 190 +++++++++++++++++++++++++++++++-
5 files changed, 201 insertions(+), 6 deletions(-)
diff --git a/arch/arm/mach-omap2/board-sdp-flash.c b/arch/arm/mach-omap2/board-sdp-flash.c
index 0604cfb..663c9c2 100644
--- a/arch/arm/mach-omap2/board-sdp-flash.c
+++ b/arch/arm/mach-omap2/board-sdp-flash.c
@@ -151,6 +151,7 @@ static struct omap_nand_platform_data sdp_nand_data = {
.nand_setup = NULL,
.gpmc_t = &nand_timings,
.dma_channel = -1, /* disable DMA in OMAP NAND driver */
+ .gpmc_irq = 20,
.dev_ready = NULL,
.devsize = 0, /* '0' for 8-bit, '1' for 16-bit device */
};
diff --git a/arch/arm/mach-omap2/board-zoom-flash.c b/arch/arm/mach-omap2/board-zoom-flash.c
index 55e173b..6a5dcf4 100644
--- a/arch/arm/mach-omap2/board-zoom-flash.c
+++ b/arch/arm/mach-omap2/board-zoom-flash.c
@@ -54,6 +54,7 @@ static struct omap_nand_platform_data zoom_nand_data = {
.nand_setup = NULL,
.gpmc_t = &nand_timings,
.dma_channel = 3, /* disable DMA in OMAP NAND driver */
+ .gpmc_irq = 20,
.dev_ready = NULL,
.devsize = 1, /* '0' for 8-bit, '1' for 16-bit device */
};
diff --git a/arch/arm/plat-omap/include/plat/nand.h b/arch/arm/plat-omap/include/plat/nand.h
index 6ba88d2..8ba2e3e 100644
--- a/arch/arm/plat-omap/include/plat/nand.h
+++ b/arch/arm/plat-omap/include/plat/nand.h
@@ -20,6 +20,7 @@ struct omap_nand_platform_data {
int (*nand_setup)(void);
int (*dev_ready)(struct omap_nand_platform_data *);
int dma_channel;
+ int gpmc_irq;
unsigned long phys_base;
void __iomem *gpmc_cs_baseaddr;
void __iomem *gpmc_baseaddr;
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 42e5ea4..376da8c 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -85,6 +85,9 @@ config MTD_NAND_OMAP_PREFETCH
help
The NAND device can be accessed for Read/Write using GPMC PREFETCH engine
to improve the performance.
+ GPMC PREFETCH can be configured eigther in MPU interrupt mode or in DMA
+ interrupt mode. If not selected any of them prefetch will be used in
+ polling mode.
config MTD_NAND_OMAP_PREFETCH_DMA
depends on MTD_NAND_OMAP_PREFETCH
@@ -93,7 +96,16 @@ config MTD_NAND_OMAP_PREFETCH_DMA
help
The GPMC PREFETCH engine can be configured eigther in MPU interrupt mode
or in DMA interrupt mode.
- Say y for DMA mode or MPU mode will be used
+ Say y for DMA mode
+
+config MTD_NAND_OMAP_PREFETCH_IRQ
+ depends on MTD_NAND_OMAP_PREFETCH && !MTD_NAND_OMAP_PREFETCH_DMA
+ bool "IRQ mode"
+ default n
+ help
+ The GPMC PREFETCH engine can be configured eigther in MPU interrupt mode
+ or in DMA interrupt mode.
+ Say y for IRQ mode
config MTD_NAND_TS7250
tristate "NAND Flash device on TS-7250 board"
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index ceb3877..5b49c84 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -11,6 +11,7 @@
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/delay.h>
+#include <linux/interrupt.h>
#include <linux/jiffies.h>
#include <linux/sched.h>
#include <linux/mtd/mtd.h>
@@ -111,17 +112,27 @@ module_param(use_prefetch, bool, 0);
MODULE_PARM_DESC(use_prefetch, "enable/disable use of PREFETCH");
#ifdef CONFIG_MTD_NAND_OMAP_PREFETCH_DMA
+const int use_interrupt;
static int use_dma = 1;
/* "modprobe ... use_dma=0" etc */
module_param(use_dma, bool, 0);
-MODULE_PARM_DESC(use_dma, "enable/disable use of DMA");
+MODULE_PARM_DESC(use_dma, "enable/disable use of DMA mode");
+#elif defined(CONFIG_MTD_NAND_OMAP_PREFETCH_IRQ)
+const int use_dma;
+static int use_interrupt = 1;
+
+/* "modprobe ... use_dma=0" etc */
+module_param(use_interrupt, bool, 0);
+MODULE_PARM_DESC(use_interrupt, "enable/disable use of IRQ mode");
#else
const int use_dma;
+const int use_interrupt;
#endif
#else
const int use_prefetch;
const int use_dma;
+const int use_interrupt;
#endif
struct omap_nand_info {
@@ -139,6 +150,8 @@ struct omap_nand_info {
void __iomem *nand_pref_fifo_add;
struct completion comp;
int dma_ch;
+ int gpmc_irq;
+ u_char *buf;
};
/**
@@ -500,6 +513,151 @@ static void omap_write_buf_dma_pref(struct mtd_info *mtd,
omap_nand_dma_transfer(mtd, buf, len, 0x1);
}
+/*
+ * omap_nand_irq - GMPC irq handler
+ * @this_irq: gpmc irq number
+ * @dev: omap_nand_info structure pointer is passed here
+ */
+static irqreturn_t omap_nand_irq(int this_irq, void *dev)
+{
+ struct omap_nand_info *info = (struct omap_nand_info *) dev;
+ u32 irq_enb = 0, pref_status = 0, bytes = 0;
+ u32 irq_stats = __raw_readl(info->gpmc_baseaddr + GPMC_IRQSTATUS);
+ u32 pref_config = __raw_readl(info->gpmc_baseaddr +
+ GPMC_PREFETCH_CONFIG1);
+
+ if (pref_config & 0x1) { /* checks for write operaiton */
+ if (irq_stats & 0x2)
+ goto done;
+
+ u32 *p = (u32 *) info->buf;
+ pref_status = gpmc_prefetch_status();
+ bytes = ((pref_status >> 24) & 0x7F);
+ if ((0x03 & ((unsigned)p)) == 0 && (0x03 & bytes) == 0)
+ iowrite32_rep(info->nand_pref_fifo_add, p, bytes >> 2);
+ else if ((0x01 & ((unsigned)p)) == 0 && (0x01 & bytes) == 0)
+ iowrite16_rep(info->nand_pref_fifo_add, p, bytes >> 1);
+ else
+ iowrite8_rep(info->nand_pref_fifo_add, p, bytes);
+ info->buf = info->buf + bytes;
+
+ } else {
+ u32 *p = (u32 *) info->buf;
+ pref_status = gpmc_prefetch_status();
+ bytes = ((pref_status >> 24) & 0x7F);
+ if ((0x03 & ((unsigned)p)) == 0 && (0x03 & bytes) == 0)
+ ioread32_rep(info->nand_pref_fifo_add, p, bytes >> 2);
+ else if ((0x01 & ((unsigned)p)) == 0 && (0x01 & bytes) == 0)
+ ioread16_rep(info->nand_pref_fifo_add, p, bytes >> 1);
+ else
+ ioread8_rep(info->nand_pref_fifo_add, p, bytes);
+ info->buf = info->buf + bytes;
+
+ if (irq_stats & 0x2)
+ goto done;
+ }
+ __raw_writel(irq_stats, info->gpmc_baseaddr + GPMC_IRQSTATUS);
+ irq_stats = __raw_readl(info->gpmc_baseaddr + GPMC_IRQSTATUS);
+
+ return IRQ_HANDLED;
+
+done:
+ complete(&info->comp);
+ irq_enb = __raw_readl(info->gpmc_baseaddr + GPMC_IRQENABLE);
+ __raw_writel((irq_enb & ~0x3), info->gpmc_baseaddr + GPMC_IRQENABLE);
+ __raw_writel(irq_stats, info->gpmc_baseaddr + GPMC_IRQSTATUS);
+ irq_stats = __raw_readl(info->gpmc_baseaddr + GPMC_IRQSTATUS);
+
+ return IRQ_HANDLED;
+}
+
+/*
+ * omap_read_buf_irq_pref - read data from NAND controller into buffer
+ * @mtd: MTD device structure
+ * @buf: buffer to store date
+ * @len: number of bytes to read
+ */
+static void omap_read_buf_irq_pref(struct mtd_info *mtd, u_char *buf, int len)
+{
+ struct omap_nand_info *info = container_of(mtd,
+ struct omap_nand_info, mtd);
+ u32 irq_enb = __raw_readl(info->gpmc_baseaddr + GPMC_IRQENABLE);
+ int ret = 0;
+
+ if (len <= mtd->oobsize) {
+ omap_read_buf_pref(mtd, buf, len);
+ return;
+ }
+
+ info->buf = buf;
+ init_completion(&info->comp);
+
+ /* configure and start prefetch transfer */
+ ret = gpmc_prefetch_enable(info->gpmc_cs, 0x0, len, 0x0);
+ if (ret)
+ /* PFPW engine is busy, use cpu copy methode */
+ goto out_copy;
+
+ __raw_writel((irq_enb | 0x3), info->gpmc_baseaddr + GPMC_IRQENABLE);
+
+ /* setup and start DMA using dma_addr */
+ wait_for_completion(&info->comp);
+
+ /* disable and stop the PFPW engine */
+ gpmc_prefetch_reset();
+
+ return;
+out_copy:
+ if (info->nand.options & NAND_BUSWIDTH_16)
+ omap_read_buf16(mtd, buf, len);
+ else
+ omap_read_buf8(mtd, buf, len);
+}
+
+/*
+ * omap_write_buf_irq_pref - write buffer to NAND controller
+ * @mtd: MTD device structure
+ * @buf: data buffer
+ * @len: number of bytes to write
+ */
+static void omap_write_buf_irq_pref(struct mtd_info *mtd,
+ const u_char *buf, int len)
+{
+ struct omap_nand_info *info = container_of(mtd,
+ struct omap_nand_info, mtd);
+ u32 irq_enb = __raw_readl(info->gpmc_baseaddr + GPMC_IRQENABLE);
+ int ret = 0;
+
+ if (len <= mtd->oobsize) {
+ omap_write_buf_pref(mtd, buf, len);
+ return;
+ }
+
+ info->buf = (u_char *) buf;
+ init_completion(&info->comp);
+
+ /* configure and start prefetch transfer */
+ ret = gpmc_prefetch_enable(info->gpmc_cs, 0x0, len, 0x1);
+ if (ret)
+ /* PFPW engine is busy, use cpu copy methode */
+ goto out_copy;
+
+ __raw_writel((irq_enb | 0x3), info->gpmc_baseaddr + GPMC_IRQENABLE);
+
+ /* setup and start DMA using dma_addr */
+ wait_for_completion(&info->comp);
+
+ /* disable and stop the PFPW engine */
+ gpmc_prefetch_reset();
+
+ return;
+out_copy:
+ if (info->nand.options & NAND_BUSWIDTH_16)
+ omap_write_buf16(mtd, buf, len);
+ else
+ omap_write_buf8(mtd, buf, len);
+}
+
/**
* omap_verify_buf - Verify chip data against buffer
* @mtd: MTD device structure
@@ -895,6 +1053,7 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
info->gpmc_cs = pdata->cs;
info->gpmc_baseaddr = pdata->gpmc_baseaddr;
info->gpmc_cs_baseaddr = pdata->gpmc_cs_baseaddr;
+ info->gpmc_irq = pdata->gpmc_irq;
info->phys_base = pdata->phys_base;
info->mtd.priv = &info->nand;
@@ -961,7 +1120,20 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
info->nand.read_buf = omap_read_buf_dma_pref;
info->nand.write_buf = omap_write_buf_dma_pref;
}
+ } else if (use_interrupt) {
+ err = request_irq(info->gpmc_irq, omap_nand_irq,
+ IRQF_SHARED, info->mtd.name, info);
+ if (err) {
+ printk(KERN_INFO"failure requesting irq %i."
+ " Prefetch will work in mpu"
+ " poling mode.\n",
+ info->gpmc_irq);
+ } else {
+ info->nand.read_buf = omap_read_buf_irq_pref;
+ info->nand.write_buf = omap_write_buf_irq_pref;
+ }
}
+
} else {
if (info->nand.options & NAND_BUSWIDTH_16) {
info->nand.read_buf = omap_read_buf16;
@@ -1052,11 +1224,19 @@ static int __init omap_nand_init(void)
/* This check is required if driver is being
* loaded run time as a module
*/
- if ((1 == use_dma) && (0 == use_prefetch)) {
- printk(KERN_INFO"Wrong parameters: 'use_dma' can not be 1 "
- "without use_prefetch'. Prefetch will not be"
- " used in either mode (mpu or dma)\n");
+
+ if ((0 == use_prefetch) && (1 == (use_dma | use_interrupt))) {
+ printk(KERN_INFO "Wrong parameters: Neither 'dma' nor 'irq' "
+ "can used without 'use_prefetch' selected.\n");
+ printk(KERN_INFO "Prefetch will not be used in any mode: "
+ "poll, mpu or dma\n");
+ } else if ((1 == use_prefetch) && (1 == (use_interrupt & use_dma))) {
+ printk(KERN_INFO "Wrong parameters: Both DMA and IRQ"
+ " modes can not be used together.\n");
+ printk(KERN_INFO "It has to be selected at compile "
+ "time and same will be used.\n");
}
+
return platform_driver_register(&omap_nand_driver);
}
--
1.5.4.7
^ permalink raw reply related [flat|nested] 102+ messages in thread
* [PATCH] omap-3630 NAND: enable NAND io in prefetch-irq mode
2010-04-13 17:37 ` [PATCH] omap3: NAND Prefetch in IRQ mode support Sukumar Ghorai
@ 2010-04-13 17:37 ` Sukumar Ghorai
2010-04-13 17:37 ` [PATCH] omap: NAND: ecc layout select from board file Sukumar Ghorai
0 siblings, 1 reply; 102+ messages in thread
From: Sukumar Ghorai @ 2010-04-13 17:37 UTC (permalink / raw)
To: linux-omap; +Cc: Sukumar Ghorai
Update config file to enable NAND in prefetch IRQ mode for ZOOM3 and 3630SDP .
Signed-off-by: Sukumar Ghorai <s-ghorai@ti.com>
---
arch/arm/configs/omap_3630sdp_defconfig | 1 +
arch/arm/configs/omap_zoom3_defconfig | 1 +
2 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/arch/arm/configs/omap_3630sdp_defconfig b/arch/arm/configs/omap_3630sdp_defconfig
index a623927..9dfce1a
--- a/arch/arm/configs/omap_3630sdp_defconfig
+++ b/arch/arm/configs/omap_3630sdp_defconfig
@@ -525,6 +525,7 @@ CONFIG_MTD_NAND=y
CONFIG_MTD_NAND_OMAP2=y
CONFIG_MTD_NAND_OMAP_PREFETCH=y
# CONFIG_MTD_NAND_OMAP_PREFETCH_DMA is not set
+CONFIG_MTD_NAND_OMAP_PREFETCH_IRQ=y
CONFIG_MTD_NAND_IDS=y
# CONFIG_MTD_NAND_DISKONCHIP is not set
# CONFIG_MTD_NAND_NANDSIM is not set
diff --git a/arch/arm/configs/omap_zoom3_defconfig b/arch/arm/configs/omap_zoom3_defconfig
index 1a12e3e..27b16ed
--- a/arch/arm/configs/omap_zoom3_defconfig
+++ b/arch/arm/configs/omap_zoom3_defconfig
@@ -534,6 +534,7 @@ CONFIG_MTD_NAND=y
CONFIG_MTD_NAND_OMAP2=y
CONFIG_MTD_NAND_OMAP_PREFETCH=y
# CONFIG_MTD_NAND_OMAP_PREFETCH_DMA is not set
+CONFIG_MTD_NAND_OMAP_PREFETCH_IRQ=y
CONFIG_MTD_NAND_IDS=y
# CONFIG_MTD_NAND_DISKONCHIP is not set
# CONFIG_MTD_NAND_NANDSIM is not set
--
1.5.4.7
^ permalink raw reply related [flat|nested] 102+ messages in thread
* [PATCH] omap: NAND: ecc layout select from board file
2010-04-13 17:37 ` [PATCH] omap-3630 NAND: enable NAND io in prefetch-irq mode Sukumar Ghorai
@ 2010-04-13 17:37 ` Sukumar Ghorai
2010-04-13 17:37 ` [PATCH] omap: NAND: Making ecc layout as compatible with romcode ecc Sukumar Ghorai
0 siblings, 1 reply; 102+ messages in thread
From: Sukumar Ghorai @ 2010-04-13 17:37 UTC (permalink / raw)
To: linux-omap; +Cc: Sukumar Ghorai, Vimal Singh
This patch makes it possible to select sw or hw (different layout options)
ecc scheme supported by omap nand driver. And hw ecc layout selected for
sdp and zoom boards, by default.
Signed-off-by: Sukumar Ghorai <s-ghorai@ti.com>
Signed-off-by: Vimal Singh <vimalsingh@ti.com>
---
arch/arm/mach-omap2/board-sdp-flash.c | 1 +
arch/arm/mach-omap2/board-zoom-flash.c | 1 +
arch/arm/plat-omap/include/plat/nand.h | 4 ++++
drivers/mtd/nand/omap2.c | 28 ++++++++++++----------------
4 files changed, 18 insertions(+), 16 deletions(-)
diff --git a/arch/arm/mach-omap2/board-sdp-flash.c b/arch/arm/mach-omap2/board-sdp-flash.c
index 663c9c2..29e0768
--- a/arch/arm/mach-omap2/board-sdp-flash.c
+++ b/arch/arm/mach-omap2/board-sdp-flash.c
@@ -162,6 +162,7 @@ __init board_nand_init(struct flash_partitions sdp_nand_parts, u8 cs)
sdp_nand_data.cs = cs;
sdp_nand_data.parts = sdp_nand_parts.parts;
sdp_nand_data.nr_parts = sdp_nand_parts.nr_parts;
+ sdp_nand_data.ecc_opt = 0x1; /* HW ECC in default layout */
if (cpu_is_omap3630())
sdp_nand_data.devsize = 1; /* 0: 8-bit, 1: 16-bit device */
diff --git a/arch/arm/mach-omap2/board-zoom-flash.c b/arch/arm/mach-omap2/board-zoom-flash.c
index 6a5dcf4..1547bdb
--- a/arch/arm/mach-omap2/board-zoom-flash.c
+++ b/arch/arm/mach-omap2/board-zoom-flash.c
@@ -71,6 +71,7 @@ void __init zoom_flash_init(struct flash_partitions zoom_nand_parts[], int cs)
zoom_nand_data.cs = cs;
zoom_nand_data.parts = zoom_nand_parts[0].parts;
zoom_nand_data.nr_parts = zoom_nand_parts[0].nr_parts;
+ zoom_nand_data.ecc_opt = 0x1; /* HW ECC in default layout */
zoom_nand_data.gpmc_baseaddr = (void *)(gpmc_base_add);
zoom_nand_data.gpmc_cs_baseaddr = (void *)(gpmc_base_add +
GPMC_CS0_BASE + cs * GPMC_CS_SIZE);
diff --git a/arch/arm/plat-omap/include/plat/nand.h b/arch/arm/plat-omap/include/plat/nand.h
index 8ba2e3e..b2ccd68 100644
--- a/arch/arm/plat-omap/include/plat/nand.h
+++ b/arch/arm/plat-omap/include/plat/nand.h
@@ -25,6 +25,10 @@ struct omap_nand_platform_data {
void __iomem *gpmc_cs_baseaddr;
void __iomem *gpmc_baseaddr;
int devsize;
+ int ecc_opt; /* 0x0 - sw ecc
+ * 0x1 - hw ecc default ecc layout
+ * 0x2 - hw ecc in romcode layout
+ */
};
/* size (4 KiB) for IO mapping */
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 5b49c84..b42d058
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -31,7 +31,6 @@
#define GPMC_BUF_FULL 0x00000001
#define GPMC_BUF_EMPTY 0x00000000
-#ifdef CONFIG_MTD_NAND_OMAP_HWECC
#define NAND_Ecc_P1e (1 << 0)
#define NAND_Ecc_P2e (1 << 1)
#define NAND_Ecc_P4e (1 << 2)
@@ -98,7 +97,6 @@
#define P4e_s(a) (TF(a & NAND_Ecc_P4e) << 0)
#define P4o_s(a) (TF(a & NAND_Ecc_P4o) << 1)
-#endif /* CONFIG_MTD_NAND_OMAP_HWECC */
#ifdef CONFIG_MTD_PARTITIONS
static const char *part_probes[] = { "cmdlinepart", NULL };
@@ -679,7 +677,6 @@ static int omap_verify_buf(struct mtd_info *mtd, const u_char * buf, int len)
return 0;
}
-#ifdef CONFIG_MTD_NAND_OMAP_HWECC
/**
* omap_hwecc_init - Initialize the HW ECC for NAND flash in GPMC controller
* @mtd: MTD device structure
@@ -957,7 +954,6 @@ static void omap_enable_hwecc(struct mtd_info *mtd, int mode)
__raw_writel(val, info->gpmc_baseaddr + GPMC_ECC_CONFIG);
}
-#endif
/**
* omap_wait - wait until the command is done
@@ -1145,19 +1141,19 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
}
info->nand.verify_buf = omap_verify_buf;
-#ifdef CONFIG_MTD_NAND_OMAP_HWECC
- info->nand.ecc.bytes = 3;
- info->nand.ecc.size = 512;
- info->nand.ecc.calculate = omap_calculate_ecc;
- info->nand.ecc.hwctl = omap_enable_hwecc;
- info->nand.ecc.correct = omap_correct_data;
- info->nand.ecc.mode = NAND_ECC_HW;
+ if (pdata->ecc_opt & 0x3) {
+ info->nand.ecc.bytes = 3;
+ info->nand.ecc.size = 512;
+ info->nand.ecc.calculate = omap_calculate_ecc;
+ info->nand.ecc.hwctl = omap_enable_hwecc;
+ info->nand.ecc.correct = omap_correct_data;
+ info->nand.ecc.mode = NAND_ECC_HW;
- /* init HW ECC */
- omap_hwecc_init(&info->mtd);
-#else
- info->nand.ecc.mode = NAND_ECC_SOFT;
-#endif
+ /* init HW ECC */
+ omap_hwecc_init(&info->mtd);
+ } else {
+ info->nand.ecc.mode = NAND_ECC_SOFT;
+ }
/* DIP switches on some boards change between 8 and 16 bit
* bus widths for flash. Try the other width if the first try fails.
--
1.5.4.7
^ permalink raw reply related [flat|nested] 102+ messages in thread
* [PATCH] omap: NAND: Making ecc layout as compatible with romcode ecc
2010-04-13 17:37 ` [PATCH] omap: NAND: ecc layout select from board file Sukumar Ghorai
@ 2010-04-13 17:37 ` Sukumar Ghorai
0 siblings, 0 replies; 102+ messages in thread
From: Sukumar Ghorai @ 2010-04-13 17:37 UTC (permalink / raw)
To: linux-omap; +Cc: Sukumar Ghorai, Vimal Singh
This patch overrides nand ecc layout and bad block descriptor (for 8-bit
device) to support hw ecc in romcode layout. So as to have in sync with ecc
layout throughout; i.e. x-laod, u-boot and kernel.
This patch also enables to use romcode ecc for spd and zoom, by default.
This enables to flash x-load, u-boot, kernel, FS images from kernel itself
and compatiable with other tools.
Signed-off-by: Sukumar Ghorai <s-ghorai@ti.com>
Signed-off-by: Vimal Singh <vimalsingh@ti.com>
---
arch/arm/mach-omap2/board-sdp-flash.c | 2 +-
arch/arm/mach-omap2/board-zoom-flash.c | 2 +-
drivers/mtd/nand/omap2.c | 42 ++++++++++++++++++++++++++++++++
3 files changed, 44 insertions(+), 2 deletions(-)
diff --git a/arch/arm/mach-omap2/board-sdp-flash.c b/arch/arm/mach-omap2/board-sdp-flash.c
index 29e0768..f1002cf 100644
--- a/arch/arm/mach-omap2/board-sdp-flash.c
+++ b/arch/arm/mach-omap2/board-sdp-flash.c
@@ -162,7 +162,7 @@ __init board_nand_init(struct flash_partitions sdp_nand_parts, u8 cs)
sdp_nand_data.cs = cs;
sdp_nand_data.parts = sdp_nand_parts.parts;
sdp_nand_data.nr_parts = sdp_nand_parts.nr_parts;
- sdp_nand_data.ecc_opt = 0x1; /* HW ECC in default layout */
+ sdp_nand_data.ecc_opt = 0x2; /* HW ECC layout as in ROMCODE */
if (cpu_is_omap3630())
sdp_nand_data.devsize = 1; /* 0: 8-bit, 1: 16-bit device */
diff --git a/arch/arm/mach-omap2/board-zoom-flash.c b/arch/arm/mach-omap2/board-zoom-flash.c
index 1547bdb..53eeaa6 100644
--- a/arch/arm/mach-omap2/board-zoom-flash.c
+++ b/arch/arm/mach-omap2/board-zoom-flash.c
@@ -71,7 +71,7 @@ void __init zoom_flash_init(struct flash_partitions zoom_nand_parts[], int cs)
zoom_nand_data.cs = cs;
zoom_nand_data.parts = zoom_nand_parts[0].parts;
zoom_nand_data.nr_parts = zoom_nand_parts[0].nr_parts;
- zoom_nand_data.ecc_opt = 0x1; /* HW ECC in default layout */
+ zoom_nand_data.ecc_opt = 0x2; /* HW ECC in romcode layout */
zoom_nand_data.gpmc_baseaddr = (void *)(gpmc_base_add);
zoom_nand_data.gpmc_cs_baseaddr = (void *)(gpmc_base_add +
GPMC_CS0_BASE + cs * GPMC_CS_SIZE);
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index b42d058..1ff5609 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -152,6 +152,39 @@ struct omap_nand_info {
u_char *buf;
};
+static struct nand_ecclayout hw_x8_romcode_oob_64 = {
+ .eccbytes = 12,
+ .eccpos = {
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
+ },
+ .oobfree = {
+ {.offset = 13,
+ .length = 51}
+ }
+};
+
+/* Define some generic bad / good block scan pattern which are used
+ * while scanning a device for factory marked good / bad blocks
+ */
+static uint8_t scan_ff_pattern[] = { 0xff };
+static struct nand_bbt_descr bb_descrip_flashbased = {
+ .options = NAND_BBT_SCANEMPTY | NAND_BBT_SCANALLPAGES,
+ .offs = 0,
+ .len = 1,
+ .pattern = scan_ff_pattern,
+};
+
+static struct nand_ecclayout hw_x16_romcode_oob_64 = {
+ .eccbytes = 12,
+ .eccpos = {
+ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13
+ },
+ .oobfree = {
+ {.offset = 14,
+ .length = 50}
+ }
+};
+
/**
* omap_nand_wp - This function enable or disable the Write Protect feature
* @mtd: MTD device structure
@@ -1142,6 +1175,15 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
info->nand.verify_buf = omap_verify_buf;
if (pdata->ecc_opt & 0x3) {
+ if (pdata->ecc_opt == 0x2) {
+ if (info->nand.options & NAND_BUSWIDTH_16) {
+ info->nand.ecc.layout = &hw_x16_romcode_oob_64;
+ } else {
+ info->nand.ecc.layout = &hw_x8_romcode_oob_64;
+ info->nand.badblock_pattern =
+ &bb_descrip_flashbased;
+ }
+ }
info->nand.ecc.bytes = 3;
info->nand.ecc.size = 512;
info->nand.ecc.calculate = omap_calculate_ecc;
--
1.5.4.7
^ permalink raw reply related [flat|nested] 102+ messages in thread
* [PATCH] nand support on omap3 boards
[not found] <Sukumar Ghorai <s-ghorai@ti.com>
2010-04-06 12:29 ` [PATCH 0/2] OMAP: Flash device support 3630 sdp board Sukumar Ghorai
2010-04-13 17:37 ` [PATCH] nand support on omap3 boards Sukumar Ghorai
@ 2010-04-13 17:44 ` Sukumar Ghorai
2010-04-16 11:32 ` [PATCH 0/6] nand prefetch-irq support and ecc layout chanage Sukumar Ghorai
` (12 subsequent siblings)
15 siblings, 0 replies; 102+ messages in thread
From: Sukumar Ghorai @ 2010-04-13 17:44 UTC (permalink / raw)
To: linux-omap; +Cc: Sukumar Ghorai
The following set of patches applies on top of the Tony's master branch.
And these are the patches required to enable nand (nor and onenand for sdp
only) for different platform.
Sukumar Ghorai (3):
OMAP: ZOOM: Introducing 'board-zoom-flash.c'
omap3: add support for NAND on zoom2 board
omap3: add support for NAND on zoom3 board
omap-3630-sdp : Add support for Flash
omap-3630-sdp: enable Flash device support
omap3: add support for NAND on LDP board
zoom2: enable NAND support
zoom3: enable NAND support
arch/arm/configs/omap_3630sdp_defconfig | 77 +++++++++++++++++-
arch/arm/configs/omap_zoom2_defconfig | 90 ++++++++++++++++++++-
arch/arm/configs/omap_zoom3_defconfig | 90 ++++++++++++++++++++-
arch/arm/mach-omap2/Makefile | 4 +
arch/arm/mach-omap2/board-3630sdp.c | 110 +++++++++++++++++++++++++
arch/arm/mach-omap2/board-ldp.c | 41 +++++++++
arch/arm/mach-omap2/board-sdp-flash.c | 2 +
arch/arm/mach-omap2/board-zoom-flash.c | 82 ++++++++++++++++++
arch/arm/mach-omap2/board-zoom2.c | 49 +++++++++++
arch/arm/mach-omap2/board-zoom3.c | 48 +++++++++++
arch/arm/mach-omap2/include/mach/board-zoom.h | 11 +++
11 files changed, 601 insertions(+), 3 deletions(-) create mode 100644 arch/arm/mach-omap2/board-zoom-flash.c
^ permalink raw reply [flat|nested] 102+ messages in thread
* Re: [PATCH] nand support on omap3 boards
2010-04-13 17:37 ` [PATCH] nand support on omap3 boards Sukumar Ghorai
2010-04-13 17:37 ` [PATCH 8/8] omap3: GPMC register definition at common location Sukumar Ghorai
@ 2010-04-14 4:35 ` Vimal Singh
2010-04-14 4:37 ` Vimal Singh
2010-04-14 4:38 ` Ghorai, Sukumar
1 sibling, 2 replies; 102+ messages in thread
From: Vimal Singh @ 2010-04-14 4:35 UTC (permalink / raw)
To: Sukumar Ghorai; +Cc: linux-omap
You post this mail in previous thread. Do not do that. ($SUBJECT is
same as last one).
Post it in different thread.
And why this is not posted as a series?
In fact these patches should be posted in two set of patches:
1. patches related to IRQ mode support
2. patches related ROM code ecc layout
And IMHO, these patches should in revers order:
> omap: NAND: ecc layout select from board file
> omap: NAND: Making ecc layout as compatible with romcode ecc
One more thing all these patches should also be posted to MTD list. In
fact, most of these patches should go through mtd tree itself.
--
Regards,
Vimal Singh
On Tue, Apr 13, 2010 at 11:07 PM, Sukumar Ghorai <s-ghorai@ti.com> wrote:
> The following set of patches applies on top of the Tony's master branch.
> And dependency on following series of patch -
>
>
> Sukumar Ghorai (3):
> omap3: GPMC register definition at common location
> omap3: NAND Prefetch in IRQ mode support
> omap-3630 NAND: enable NAND io in prefetch-irq mode
> omap: NAND: ecc layout select from board file
> omap: NAND: Making ecc layout as compatible with romcode ecc
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 102+ messages in thread
* Re: [PATCH] nand support on omap3 boards
2010-04-14 4:35 ` [PATCH] nand support on omap3 boards Vimal Singh
@ 2010-04-14 4:37 ` Vimal Singh
2010-04-14 4:38 ` Ghorai, Sukumar
1 sibling, 0 replies; 102+ messages in thread
From: Vimal Singh @ 2010-04-14 4:37 UTC (permalink / raw)
To: Sukumar Ghorai; +Cc: linux-omap
On Wed, Apr 14, 2010 at 10:05 AM, Vimal Singh <vimal.newwork@gmail.com> wrote:
> You post this mail in previous thread. Do not do that. ($SUBJECT is
> same as last one).
> Post it in different thread.
>
> And why this is not posted as a series?
> In fact these patches should be posted in two set of patches:
> 1. patches related to IRQ mode support
> 2. patches related ROM code ecc layout
>
> And IMHO, these patches should in revers order:
>> omap: NAND: ecc layout select from board file
>> omap: NAND: Making ecc layout as compatible with romcode ecc
I saw them again. Please discard this comment. It looks OK to me.
--
Regards,
Vimal Singh
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 102+ messages in thread
* RE: [PATCH] nand support on omap3 boards
2010-04-14 4:35 ` [PATCH] nand support on omap3 boards Vimal Singh
2010-04-14 4:37 ` Vimal Singh
@ 2010-04-14 4:38 ` Ghorai, Sukumar
1 sibling, 0 replies; 102+ messages in thread
From: Ghorai, Sukumar @ 2010-04-14 4:38 UTC (permalink / raw)
To: Vimal Singh; +Cc: linux-omap@vger.kernel.org
> -----Original Message-----
> From: Vimal Singh [mailto:vimal.newwork@gmail.com]
> Sent: 2010-04-14 10:05
> To: Ghorai, Sukumar
> Cc: linux-omap@vger.kernel.org
> Subject: Re: [PATCH] nand support on omap3 boards
>
> You post this mail in previous thread. Do not do that. ($SUBJECT is
> same as last one).
> Post it in different thread.
>
> And why this is not posted as a series?
> In fact these patches should be posted in two set of patches:
> 1. patches related to IRQ mode support
> 2. patches related ROM code ecc layout
[Ghorai] Agree.
>
> And IMHO, these patches should in revers order:
> > omap: NAND: ecc layout select from board file
> > omap: NAND: Making ecc layout as compatible with romcode ecc
[Ghorai] But this is the order it's in SYNC/ manju's dev tree. I think.
>
> One more thing all these patches should also be posted to MTD list. In
> fact, most of these patches should go through mtd tree itself.
[Ghorai] ok. I will..
>
> --
> Regards,
> Vimal Singh
>
>
>
> On Tue, Apr 13, 2010 at 11:07 PM, Sukumar Ghorai <s-ghorai@ti.com> wrote:
> > The following set of patches applies on top of the Tony's master
> branch.
> > And dependency on following series of patch -
> >
> >
> > Sukumar Ghorai (3):
> > omap3: GPMC register definition at common location
> > omap3: NAND Prefetch in IRQ mode support
> > omap-3630 NAND: enable NAND io in prefetch-irq mode
> > omap: NAND: ecc layout select from board file
> > omap: NAND: Making ecc layout as compatible with romcode ecc
> >
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at http://vger.kernel.org/majordomo-info.html
> >
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 102+ messages in thread
* [PATCH 0/6] nand prefetch-irq support and ecc layout chanage
[not found] <Sukumar Ghorai <s-ghorai@ti.com>
` (2 preceding siblings ...)
2010-04-13 17:44 ` Sukumar Ghorai
@ 2010-04-16 11:32 ` Sukumar Ghorai
2010-04-16 11:34 ` [PATCH 1/6] omap3: GPMC register definition at common location Sukumar Ghorai
` (11 subsequent siblings)
15 siblings, 0 replies; 102+ messages in thread
From: Sukumar Ghorai @ 2010-04-16 11:32 UTC (permalink / raw)
To: linux-mtd
Cc: sbranden, leochen, David.Woodhouse, linux-omap, tony,
vimal.newwork, Sukumar Ghorai
The main motivations behind this patch series are -
1. support NAND I/O in irq mode.
2. support of different ECC schema.
3. also to make ecc layout as like in romcode ecc layout
The following set of patches applies on top of the master branch. And
is dependent on the following patches not yet applied onto this branch.
https://patchwork.kernel.org/patch/92220/
https://patchwork.kernel.org/patch/92232/
https://patchwork.kernel.org/patch/92221/
https://patchwork.kernel.org/patch/92230/
https://patchwork.kernel.org/patch/92224/
https://patchwork.kernel.org/patch/92222/
https://patchwork.kernel.org/patch/92223/
https://patchwork.kernel.org/patch/92229/
Sukumar Ghorai (6):
omap: NAND: Making ecc layout as compatible with romcode ecc
omap: NAND: ecc layout select from board file
omap-3630 NAND: enable NAND io in prefetch-irq mode
OMAP NAND: configurable fifo threshold to gain the throughput
omap3: NAND Prefetch in IRQ mode support
omap3: GPMC register definition at common location
arch/arm/configs/omap_3630sdp_defconfig | 1 +
arch/arm/configs/omap_zoom3_defconfig | 1 +
arch/arm/mach-omap2/board-sdp-flash.c | 2 +
arch/arm/mach-omap2/board-zoom-flash.c | 2 +
arch/arm/mach-omap2/gpmc.c | 47 +-----
arch/arm/plat-omap/include/plat/gpmc.h | 41 ++++-
arch/arm/plat-omap/include/plat/nand.h | 5 +
drivers/mtd/nand/Kconfig | 14 ++-
drivers/mtd/nand/omap2.c | 275 +++++++++++++++++++++++++++----
9 files changed, 309 insertions(+), 79 deletions(-)
^ permalink raw reply [flat|nested] 102+ messages in thread
* [PATCH 1/6] omap3: GPMC register definition at common location
[not found] <Sukumar Ghorai <s-ghorai@ti.com>
` (3 preceding siblings ...)
2010-04-16 11:32 ` [PATCH 0/6] nand prefetch-irq support and ecc layout chanage Sukumar Ghorai
@ 2010-04-16 11:34 ` Sukumar Ghorai
2010-04-16 11:35 ` [PATCH 2/6] omap3: NAND Prefetch in IRQ mode support Sukumar Ghorai
` (10 subsequent siblings)
15 siblings, 0 replies; 102+ messages in thread
From: Sukumar Ghorai @ 2010-04-16 11:34 UTC (permalink / raw)
To: linux-mtd
Cc: sbranden, leochen, David.Woodhouse, linux-omap, tony,
vimal.newwork, Sukumar Ghorai, Vimal Singh
GPMC register definition move to common place in gpmc.h.
Signed-off-by: Sukumar Ghorai <s-ghorai@ti.com>
Signed-off-by: Vimal Singh <vimalsingh@ti.com>
---
arch/arm/mach-omap2/gpmc.c | 38 +------------------------------
arch/arm/plat-omap/include/plat/gpmc.h | 36 +++++++++++++++++++++++++++--
drivers/mtd/nand/omap2.c | 14 ++++-------
3 files changed, 40 insertions(+), 48 deletions(-)
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index 5bc3ca0..9c77af0
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -28,40 +28,6 @@
#include <plat/sdrc.h>
-/* GPMC register offsets */
-#define GPMC_REVISION 0x00
-#define GPMC_SYSCONFIG 0x10
-#define GPMC_SYSSTATUS 0x14
-#define GPMC_IRQSTATUS 0x18
-#define GPMC_IRQENABLE 0x1c
-#define GPMC_TIMEOUT_CONTROL 0x40
-#define GPMC_ERR_ADDRESS 0x44
-#define GPMC_ERR_TYPE 0x48
-#define GPMC_CONFIG 0x50
-#define GPMC_STATUS 0x54
-#define GPMC_PREFETCH_CONFIG1 0x1e0
-#define GPMC_PREFETCH_CONFIG2 0x1e4
-#define GPMC_PREFETCH_CONTROL 0x1ec
-#define GPMC_PREFETCH_STATUS 0x1f0
-#define GPMC_ECC_CONFIG 0x1f4
-#define GPMC_ECC_CONTROL 0x1f8
-#define GPMC_ECC_SIZE_CONFIG 0x1fc
-
-#define GPMC_CS0 0x60
-#define GPMC_CS_SIZE 0x30
-
-#define GPMC_MEM_START 0x00000000
-#define GPMC_MEM_END 0x3FFFFFFF
-#define BOOT_ROM_SPACE 0x100000 /* 1MB */
-
-#define GPMC_CHUNK_SHIFT 24 /* 16 MB */
-#define GPMC_SECTION_SHIFT 28 /* 128 MB */
-
-#define PREFETCH_FIFOTHRESHOLD (0x40 << 8)
-#define CS_NUM_SHIFT 24
-#define ENABLE_PREFETCH (0x1 << 7)
-#define DMA_MPU_MODE 2
-
/* Structure to save gpmc cs context */
struct gpmc_cs_config {
u32 config1;
@@ -112,7 +78,7 @@ void gpmc_cs_write_reg(int cs, int idx, u32 val)
{
void __iomem *reg_addr;
- reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx;
+ reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx;
__raw_writel(val, reg_addr);
}
@@ -120,7 +86,7 @@ u32 gpmc_cs_read_reg(int cs, int idx)
{
void __iomem *reg_addr;
- reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx;
+ reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx;
return __raw_readl(reg_addr);
}
diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h
index 145838a..347d212 100644
--- a/arch/arm/plat-omap/include/plat/gpmc.h
+++ b/arch/arm/plat-omap/include/plat/gpmc.h
@@ -25,10 +25,40 @@
#define GPMC_CS_NAND_ADDRESS 0x20
#define GPMC_CS_NAND_DATA 0x24
-#define GPMC_CONFIG 0x50
-#define GPMC_STATUS 0x54
+/* GPMC register offsets */
+#define GPMC_REVISION 0x00
+#define GPMC_SYSCONFIG 0x10
+#define GPMC_SYSSTATUS 0x14
+#define GPMC_IRQSTATUS 0x18
+#define GPMC_IRQENABLE 0x1c
+#define GPMC_TIMEOUT_CONTROL 0x40
+#define GPMC_ERR_ADDRESS 0x44
+#define GPMC_ERR_TYPE 0x48
+#define GPMC_CONFIG 0x50
+#define GPMC_STATUS 0x54
+#define GPMC_PREFETCH_CONFIG1 0x1e0
+#define GPMC_PREFETCH_CONFIG2 0x1e4
+#define GPMC_PREFETCH_CONTROL 0x1ec
+#define GPMC_PREFETCH_STATUS 0x1f0
+#define GPMC_ECC_CONFIG 0x1f4
+#define GPMC_ECC_CONTROL 0x1f8
+#define GPMC_ECC_SIZE_CONFIG 0x1fc
+#define GPMC_ECC1_RESULT 0x200
+
#define GPMC_CS0_BASE 0x60
-#define GPMC_CS_SIZE 0x30
+#define GPMC_CS_SIZE 0x30
+
+#define GPMC_MEM_START 0x00000000
+#define GPMC_MEM_END 0x3FFFFFFF
+#define BOOT_ROM_SPACE 0x100000 /* 1MB */
+
+#define GPMC_CHUNK_SHIFT 24 /* 16 MB */
+#define GPMC_SECTION_SHIFT 28 /* 128 MB */
+
+#define PREFETCH_FIFOTHRESHOLD (0x40 << 8)
+#define CS_NUM_SHIFT 24
+#define ENABLE_PREFETCH (0x1 << 7)
+#define DMA_MPU_MODE 2
#define GPMC_CONFIG1_WRAPBURST_SUPP (1 << 31)
#define GPMC_CONFIG1_READMULTIPLE_SUPP (1 << 30)
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index ad07d39..09a89f9
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -22,12 +22,6 @@
#include <plat/gpmc.h>
#include <plat/nand.h>
-#define GPMC_IRQ_STATUS 0x18
-#define GPMC_ECC_CONFIG 0x1F4
-#define GPMC_ECC_CONTROL 0x1F8
-#define GPMC_ECC_SIZE_CONFIG 0x1FC
-#define GPMC_ECC1_RESULT 0x200
-
#define DRIVER_NAME "omap2-nand"
#define NAND_WP_OFF 0
@@ -36,6 +30,7 @@
#define GPMC_BUF_FULL 0x00000001
#define GPMC_BUF_EMPTY 0x00000000
+#ifdef CONFIG_MTD_NAND_OMAP_HWECC
#define NAND_Ecc_P1e (1 << 0)
#define NAND_Ecc_P2e (1 << 1)
#define NAND_Ecc_P4e (1 << 2)
@@ -102,6 +97,7 @@
#define P4e_s(a) (TF(a & NAND_Ecc_P4e) << 0)
#define P4o_s(a) (TF(a & NAND_Ecc_P4o) << 1)
+#endif /* CONFIG_MTD_NAND_OMAP_HWECC */
#ifdef CONFIG_MTD_PARTITIONS
static const char *part_probes[] = { "cmdlinepart", NULL };
@@ -856,20 +852,20 @@ static int omap_dev_ready(struct mtd_info *mtd)
{
struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
mtd);
- unsigned int val = __raw_readl(info->gpmc_baseaddr + GPMC_IRQ_STATUS);
+ unsigned int val = __raw_readl(info->gpmc_baseaddr + GPMC_IRQSTATUS);
if ((val & 0x100) == 0x100) {
/* Clear IRQ Interrupt */
val |= 0x100;
val &= ~(0x0);
- __raw_writel(val, info->gpmc_baseaddr + GPMC_IRQ_STATUS);
+ __raw_writel(val, info->gpmc_baseaddr + GPMC_IRQSTATUS);
} else {
unsigned int cnt = 0;
while (cnt++ < 0x1FF) {
if ((val & 0x100) == 0x100)
return 0;
val = __raw_readl(info->gpmc_baseaddr +
- GPMC_IRQ_STATUS);
+ GPMC_IRQSTATUS);
}
}
^ permalink raw reply related [flat|nested] 102+ messages in thread
* [PATCH 2/6] omap3: NAND Prefetch in IRQ mode support
[not found] <Sukumar Ghorai <s-ghorai@ti.com>
` (4 preceding siblings ...)
2010-04-16 11:34 ` [PATCH 1/6] omap3: GPMC register definition at common location Sukumar Ghorai
@ 2010-04-16 11:35 ` Sukumar Ghorai
2010-04-16 11:35 ` [PATCH 3/6] OMAP NAND: configurable fifo threshold to gain the throughput Sukumar Ghorai
` (9 subsequent siblings)
15 siblings, 0 replies; 102+ messages in thread
From: Sukumar Ghorai @ 2010-04-16 11:35 UTC (permalink / raw)
To: linux-mtd
Cc: sbranden, leochen, David.Woodhouse, linux-omap, tony,
vimal.newwork, Sukumar Ghorai, Vimal Singh
This patch enable prefetch-irq mode for NAND.
Signed-off-by: Vimal Singh <vimalsingh@ti.com>
Signed-off-by: Sukumar Ghorai <s-ghorai@ti.com>
---
arch/arm/mach-omap2/board-sdp-flash.c | 1 +
arch/arm/mach-omap2/board-zoom-flash.c | 1 +
arch/arm/plat-omap/include/plat/nand.h | 1 +
drivers/mtd/nand/Kconfig | 14 +++-
drivers/mtd/nand/omap2.c | 180 +++++++++++++++++++++++++++++++-
5 files changed, 191 insertions(+), 6 deletions(-)
diff --git a/arch/arm/mach-omap2/board-sdp-flash.c b/arch/arm/mach-omap2/board-sdp-flash.c
index 57116e6..81b83ce
--- a/arch/arm/mach-omap2/board-sdp-flash.c
+++ b/arch/arm/mach-omap2/board-sdp-flash.c
@@ -151,6 +151,7 @@ static struct omap_nand_platform_data sdp_nand_data = {
.nand_setup = NULL,
.gpmc_t = &nand_timings,
.dma_channel = -1, /* disable DMA in OMAP NAND driver */
+ .gpmc_irq = 20,
.dev_ready = NULL,
.devsize = 0, /* '0' for 8-bit, '1' for 16-bit device */
};
diff --git a/arch/arm/mach-omap2/board-zoom-flash.c b/arch/arm/mach-omap2/board-zoom-flash.c
index 55e173b..6a5dcf4 100644
--- a/arch/arm/mach-omap2/board-zoom-flash.c
+++ b/arch/arm/mach-omap2/board-zoom-flash.c
@@ -54,6 +54,7 @@ static struct omap_nand_platform_data zoom_nand_data = {
.nand_setup = NULL,
.gpmc_t = &nand_timings,
.dma_channel = -1, /* disable DMA in OMAP NAND driver */
+ .gpmc_irq = 20,
.dev_ready = NULL,
.devsize = 1, /* '0' for 8-bit, '1' for 16-bit device */
};
diff --git a/arch/arm/plat-omap/include/plat/nand.h b/arch/arm/plat-omap/include/plat/nand.h
index 6ba88d2..8ba2e3e 100644
--- a/arch/arm/plat-omap/include/plat/nand.h
+++ b/arch/arm/plat-omap/include/plat/nand.h
@@ -20,6 +20,7 @@ struct omap_nand_platform_data {
int (*nand_setup)(void);
int (*dev_ready)(struct omap_nand_platform_data *);
int dma_channel;
+ int gpmc_irq;
unsigned long phys_base;
void __iomem *gpmc_cs_baseaddr;
void __iomem *gpmc_baseaddr;
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index b712aed..ee9abbd
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -94,6 +94,9 @@ config MTD_NAND_OMAP_PREFETCH
help
The NAND device can be accessed for Read/Write using GPMC PREFETCH engine
to improve the performance.
+ GPMC PREFETCH can be configured eigther in MPU interrupt mode or in DMA
+ interrupt mode. If not selected any of them prefetch will be used in
+ polling mode.
config MTD_NAND_OMAP_PREFETCH_DMA
depends on MTD_NAND_OMAP_PREFETCH
@@ -102,7 +105,16 @@ config MTD_NAND_OMAP_PREFETCH_DMA
help
The GPMC PREFETCH engine can be configured eigther in MPU interrupt mode
or in DMA interrupt mode.
- Say y for DMA mode or MPU mode will be used
+ Say y for DMA mode
+
+config MTD_NAND_OMAP_PREFETCH_IRQ
+ depends on MTD_NAND_OMAP_PREFETCH && !MTD_NAND_OMAP_PREFETCH_DMA
+ bool "IRQ mode"
+ default n
+ help
+ The GPMC PREFETCH engine can be configured eigther in MPU interrupt mode
+ or in DMA interrupt mode.
+ Say y for IRQ mode
config MTD_NAND_IDS
tristate
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 09a89f9..de9b058 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -11,6 +11,7 @@
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/delay.h>
+#include <linux/interrupt.h>
#include <linux/jiffies.h>
#include <linux/sched.h>
#include <linux/mtd/mtd.h>
@@ -111,17 +112,27 @@ module_param(use_prefetch, bool, 0);
MODULE_PARM_DESC(use_prefetch, "enable/disable use of PREFETCH");
#ifdef CONFIG_MTD_NAND_OMAP_PREFETCH_DMA
+const int use_interrupt;
static int use_dma = 1;
/* "modprobe ... use_dma=0" etc */
module_param(use_dma, bool, 0);
-MODULE_PARM_DESC(use_dma, "enable/disable use of DMA");
+MODULE_PARM_DESC(use_dma, "enable/disable use of DMA mode");
+#elif defined(CONFIG_MTD_NAND_OMAP_PREFETCH_IRQ)
+const int use_dma;
+static int use_interrupt = 1;
+
+/* "modprobe ... use_dma=0" etc */
+module_param(use_interrupt, bool, 0);
+MODULE_PARM_DESC(use_interrupt, "enable/disable use of IRQ mode");
#else
const int use_dma;
+const int use_interrupt;
#endif
#else
const int use_prefetch;
const int use_dma;
+const int use_interrupt;
#endif
struct omap_nand_info {
@@ -139,6 +150,8 @@ struct omap_nand_info {
void __iomem *nand_pref_fifo_add;
struct completion comp;
int dma_ch;
+ int gpmc_irq;
+ u_char *buf;
};
/**
@@ -503,6 +516,141 @@ static void omap_write_buf_dma_pref(struct mtd_info *mtd,
omap_nand_dma_transfer(mtd, (u_char *) buf, len, 0x1);
}
+/*
+ * omap_nand_irq - GMPC irq handler
+ * @this_irq: gpmc irq number
+ * @dev: omap_nand_info structure pointer is passed here
+ */
+static irqreturn_t omap_nand_irq(int this_irq, void *dev)
+{
+ struct omap_nand_info *info = (struct omap_nand_info *) dev;
+ u32 irq_enb = 0, pref_status = 0, bytes = 0;
+ u32 irq_stats = __raw_readl(info->gpmc_baseaddr + GPMC_IRQSTATUS);
+ u32 pref_config = __raw_readl(info->gpmc_baseaddr +
+ GPMC_PREFETCH_CONFIG1);
+
+ if (pref_config & 0x1) { /* checks for write operaiton */
+ if (irq_stats & 0x2)
+ goto done;
+
+ u32 *p = (u32 *) info->buf;
+ pref_status = gpmc_prefetch_status();
+ bytes = ((pref_status >> 24) & 0x7F);
+ iowrite32_rep(info->nand_pref_fifo_add, p, bytes >> 2);
+ info->buf = info->buf + bytes;
+
+ } else {
+ u32 *p = (u32 *) info->buf;
+ pref_status = gpmc_prefetch_status();
+ bytes = ((pref_status >> 24) & 0x7F);
+ ioread32_rep(info->nand_pref_fifo_add, p, bytes >> 2);
+ info->buf = info->buf + bytes;
+
+ if (irq_stats & 0x2)
+ goto done;
+ }
+ __raw_writel(irq_stats, info->gpmc_baseaddr + GPMC_IRQSTATUS);
+ irq_stats = __raw_readl(info->gpmc_baseaddr + GPMC_IRQSTATUS);
+
+ return IRQ_HANDLED;
+
+done:
+ complete(&info->comp);
+ irq_enb = __raw_readl(info->gpmc_baseaddr + GPMC_IRQENABLE);
+ __raw_writel((irq_enb & ~0x3), info->gpmc_baseaddr + GPMC_IRQENABLE);
+ __raw_writel(irq_stats, info->gpmc_baseaddr + GPMC_IRQSTATUS);
+ irq_stats = __raw_readl(info->gpmc_baseaddr + GPMC_IRQSTATUS);
+
+ return IRQ_HANDLED;
+}
+
+/*
+ * omap_read_buf_irq_pref - read data from NAND controller into buffer
+ * @mtd: MTD device structure
+ * @buf: buffer to store date
+ * @len: number of bytes to read
+ */
+static void omap_read_buf_irq_pref(struct mtd_info *mtd, u_char *buf, int len)
+{
+ struct omap_nand_info *info = container_of(mtd,
+ struct omap_nand_info, mtd);
+ u32 irq_enb = __raw_readl(info->gpmc_baseaddr + GPMC_IRQENABLE);
+ int ret = 0;
+
+ if (len <= mtd->oobsize) {
+ omap_read_buf_pref(mtd, buf, len);
+ return;
+ }
+
+ info->buf = buf;
+ init_completion(&info->comp);
+
+ /* configure and start prefetch transfer */
+ ret = gpmc_prefetch_enable(info->gpmc_cs, 0x0, len, 0x0);
+ if (ret)
+ /* PFPW engine is busy, use cpu copy methode */
+ goto out_copy;
+
+ __raw_writel((irq_enb | 0x3), info->gpmc_baseaddr + GPMC_IRQENABLE);
+
+ /* setup and start DMA using dma_addr */
+ wait_for_completion(&info->comp);
+
+ /* disable and stop the PFPW engine */
+ gpmc_prefetch_reset();
+
+ return;
+out_copy:
+ if (info->nand.options & NAND_BUSWIDTH_16)
+ omap_read_buf16(mtd, buf, len);
+ else
+ omap_read_buf8(mtd, buf, len);
+}
+
+/*
+ * omap_write_buf_irq_pref - write buffer to NAND controller
+ * @mtd: MTD device structure
+ * @buf: data buffer
+ * @len: number of bytes to write
+ */
+static void omap_write_buf_irq_pref(struct mtd_info *mtd,
+ const u_char *buf, int len)
+{
+ struct omap_nand_info *info = container_of(mtd,
+ struct omap_nand_info, mtd);
+ u32 irq_enb = __raw_readl(info->gpmc_baseaddr + GPMC_IRQENABLE);
+ int ret = 0;
+
+ if (len <= mtd->oobsize) {
+ omap_write_buf_pref(mtd, buf, len);
+ return;
+ }
+
+ info->buf = (u_char *) buf;
+ init_completion(&info->comp);
+
+ /* configure and start prefetch transfer */
+ ret = gpmc_prefetch_enable(info->gpmc_cs, 0x0, len, 0x1);
+ if (ret)
+ /* PFPW engine is busy, use cpu copy methode */
+ goto out_copy;
+
+ __raw_writel((irq_enb | 0x3), info->gpmc_baseaddr + GPMC_IRQENABLE);
+
+ /* setup and start DMA using dma_addr */
+ wait_for_completion(&info->comp);
+
+ /* disable and stop the PFPW engine */
+ gpmc_prefetch_reset();
+
+ return;
+out_copy:
+ if (info->nand.options & NAND_BUSWIDTH_16)
+ omap_write_buf16(mtd, buf, len);
+ else
+ omap_write_buf8(mtd, buf, len);
+}
+
/**
* omap_verify_buf - Verify chip data against buffer
* @mtd: MTD device structure
@@ -898,6 +1046,7 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
info->gpmc_cs = pdata->cs;
info->gpmc_baseaddr = pdata->gpmc_baseaddr;
info->gpmc_cs_baseaddr = pdata->gpmc_cs_baseaddr;
+ info->gpmc_irq = pdata->gpmc_irq;
info->phys_base = pdata->phys_base;
info->mtd.priv = &info->nand;
@@ -964,7 +1113,20 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
info->nand.read_buf = omap_read_buf_dma_pref;
info->nand.write_buf = omap_write_buf_dma_pref;
}
+ } else if (use_interrupt) {
+ err = request_irq(info->gpmc_irq, omap_nand_irq,
+ IRQF_SHARED, info->mtd.name, info);
+ if (err) {
+ printk(KERN_INFO"failure requesting irq %i."
+ " Prefetch will work in mpu"
+ " poling mode.\n",
+ info->gpmc_irq);
+ } else {
+ info->nand.read_buf = omap_read_buf_irq_pref;
+ info->nand.write_buf = omap_write_buf_irq_pref;
+ }
}
+
} else {
if (info->nand.options & NAND_BUSWIDTH_16) {
info->nand.read_buf = omap_read_buf16;
@@ -1056,11 +1218,19 @@ static int __init omap_nand_init(void)
/* This check is required if driver is being
* loaded run time as a module
*/
- if ((1 == use_dma) && (0 == use_prefetch)) {
- printk(KERN_INFO"Wrong parameters: 'use_dma' can not be 1 "
- "without use_prefetch'. Prefetch will not be"
- " used in either mode (mpu or dma)\n");
+
+ if ((0 == use_prefetch) && (1 == (use_dma | use_interrupt))) {
+ printk(KERN_INFO "Wrong parameters: Neither 'dma' nor 'irq' "
+ "can used without 'use_prefetch' selected.\n");
+ printk(KERN_INFO "Prefetch will not be used in any mode: "
+ "poll, mpu or dma\n");
+ } else if ((1 == use_prefetch) && (1 == (use_interrupt & use_dma))) {
+ printk(KERN_INFO "Wrong parameters: Both DMA and IRQ"
+ " modes can not be used together.\n");
+ printk(KERN_INFO "It has to be selected at compile "
+ "time and same will be used.\n");
}
+
return platform_driver_register(&omap_nand_driver);
}
^ permalink raw reply related [flat|nested] 102+ messages in thread
* [PATCH 3/6] OMAP NAND: configurable fifo threshold to gain the throughput
[not found] <Sukumar Ghorai <s-ghorai@ti.com>
` (5 preceding siblings ...)
2010-04-16 11:35 ` [PATCH 2/6] omap3: NAND Prefetch in IRQ mode support Sukumar Ghorai
@ 2010-04-16 11:35 ` Sukumar Ghorai
2010-04-16 12:45 ` Vimal Singh
2010-04-16 11:35 ` [PATCH 4/6] omap-3630 NAND: enable NAND io in prefetch-irq mode Sukumar Ghorai
` (8 subsequent siblings)
15 siblings, 1 reply; 102+ messages in thread
From: Sukumar Ghorai @ 2010-04-16 11:35 UTC (permalink / raw)
To: linux-mtd
Cc: sbranden, leochen, David.Woodhouse, linux-omap, tony,
vimal.newwork, Sukumar Ghorai, Vimal Singh
Configure the FIFO THREASHOLD value to 50% (32 bytes) to keep busy both
filling and to drain out of FIFO at reading and writing.
Signed-off-by: Sukumar Ghorai <s-ghorai@ti.com>
Signed-off-by: Vimal Singh <vimalsingh@ti.com>
---
arch/arm/mach-omap2/gpmc.c | 9 ++++++---
arch/arm/plat-omap/include/plat/gpmc.h | 7 +++++--
drivers/mtd/nand/omap2.c | 25 +++++++++++++------------
3 files changed, 24 insertions(+), 17 deletions(-)
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index 9c77af0..1380886 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -391,12 +391,15 @@ EXPORT_SYMBOL(gpmc_cs_free);
* @u32_count: number of bytes to be transferred
* @is_write: prefetch read(0) or write post(1) mode
*/
-int gpmc_prefetch_enable(int cs, int dma_mode,
+int gpmc_prefetch_enable(int cs, int fifo_th, int dma_mode,
unsigned int u32_count, int is_write)
{
uint32_t prefetch_config1;
- if (!(gpmc_read_reg(GPMC_PREFETCH_CONTROL))) {
+ if (fifo_th > PREFETCH_FIFOTHRESHOLD_MAX) {
+ printk(KERN_ERR "PREFETCH Fifo Threshold is not supported\n");
+ return -1;
+ } else if (!(gpmc_read_reg(GPMC_PREFETCH_CONTROL))) {
/* Set the amount of bytes to be prefetched */
gpmc_write_reg(GPMC_PREFETCH_CONFIG2, u32_count);
@@ -404,7 +407,7 @@ int gpmc_prefetch_enable(int cs, int dma_mode,
* enable the engine. Set which cs is has requested for.
*/
prefetch_config1 = ((cs << CS_NUM_SHIFT) |
- PREFETCH_FIFOTHRESHOLD |
+ PREFETCH_FIFOTHRESHOLD(fifo_th) |
ENABLE_PREFETCH |
(dma_mode << DMA_MPU_MODE) |
(0x1 & is_write));
diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h
index 347d212..a36a046 100644
--- a/arch/arm/plat-omap/include/plat/gpmc.h
+++ b/arch/arm/plat-omap/include/plat/gpmc.h
@@ -55,10 +55,13 @@
#define GPMC_CHUNK_SHIFT 24 /* 16 MB */
#define GPMC_SECTION_SHIFT 28 /* 128 MB */
-#define PREFETCH_FIFOTHRESHOLD (0x40 << 8)
+#define PREFETCH_FIFOTHRESHOLD_MAX 0x40
+#define PREFETCH_FIFOTHRESHOLD(val) (val << 8)
#define CS_NUM_SHIFT 24
#define ENABLE_PREFETCH (0x1 << 7)
#define DMA_MPU_MODE 2
+#define PREFETCH_FIFOTHRESHOLD_READ 32 /* threashold size for read */
+#define PREFETCH_FIFOTHRESHOLD_WRITE 32 /* threashold size for write */
#define GPMC_CONFIG1_WRAPBURST_SUPP (1 << 31)
#define GPMC_CONFIG1_READMULTIPLE_SUPP (1 << 30)
@@ -136,7 +139,7 @@ extern int gpmc_cs_request(int cs, unsigned long size, unsigned long *base);
extern void gpmc_cs_free(int cs);
extern int gpmc_cs_set_reserved(int cs, int reserved);
extern int gpmc_cs_reserved(int cs);
-extern int gpmc_prefetch_enable(int cs, int dma_mode,
+extern int gpmc_prefetch_enable(int cs, int fifo_th, int dma_mode,
unsigned int u32_count, int is_write);
extern void gpmc_prefetch_reset(void);
extern int gpmc_prefetch_status(void);
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index de9b058..61c0c01
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -310,7 +310,7 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len)
}
/* configure and start prefetch transfer */
- ret = gpmc_prefetch_enable(info->gpmc_cs, 0x0, len, 0x0);
+ ret = gpmc_prefetch_enable(info->gpmc_cs, 0x40, 0x0, len, 0x0);
if (ret) {
/* PFPW engine is busy, use cpu copy method */
if (info->nand.options & NAND_BUSWIDTH_16)
@@ -354,7 +354,7 @@ static void omap_write_buf_pref(struct mtd_info *mtd,
}
/* configure and start prefetch transfer */
- ret = gpmc_prefetch_enable(info->gpmc_cs, 0x0, len, 0x1);
+ ret = gpmc_prefetch_enable(info->gpmc_cs, 0x40, 0x0, len, 0x1);
if (ret) {
/* PFPW engine is busy, use cpu copy method */
if (info->nand.options & NAND_BUSWIDTH_16)
@@ -405,10 +405,11 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr,
dma_addr_t dma_addr;
int ret;
- /* The fifo depth is 64 bytes. We have a sync at each frame and frame
- * length is 64 bytes.
+ /* The fifo depth is 64 bytes max.
+ * But configure the FIFO-threahold to 32 to get a sync at each frame
+ * and frame length is 32 bytes.
*/
- int buf_len = len >> 6;
+ int buf_len = len >> 5;
if (addr >= high_memory) {
struct page *p1;
@@ -447,7 +448,7 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr,
OMAP24XX_DMA_GPMC, OMAP_DMA_SRC_SYNC);
}
/* configure and start prefetch transfer */
- ret = gpmc_prefetch_enable(info->gpmc_cs, 0x1, len, is_write);
+ ret = gpmc_prefetch_enable(info->gpmc_cs, 0x20, 0x1, len, is_write);
if (ret)
/* PFPW engine is busy, use cpu copy methode */
goto out_copy;
@@ -524,6 +525,7 @@ static void omap_write_buf_dma_pref(struct mtd_info *mtd,
static irqreturn_t omap_nand_irq(int this_irq, void *dev)
{
struct omap_nand_info *info = (struct omap_nand_info *) dev;
+ u32 *p = (u32 *) info->buf;
u32 irq_enb = 0, pref_status = 0, bytes = 0;
u32 irq_stats = __raw_readl(info->gpmc_baseaddr + GPMC_IRQSTATUS);
u32 pref_config = __raw_readl(info->gpmc_baseaddr +
@@ -533,14 +535,11 @@ static irqreturn_t omap_nand_irq(int this_irq, void *dev)
if (irq_stats & 0x2)
goto done;
- u32 *p = (u32 *) info->buf;
- pref_status = gpmc_prefetch_status();
- bytes = ((pref_status >> 24) & 0x7F);
+ bytes = PREFETCH_FIFOTHRESHOLD_WRITE;
iowrite32_rep(info->nand_pref_fifo_add, p, bytes >> 2);
info->buf = info->buf + bytes;
} else {
- u32 *p = (u32 *) info->buf;
pref_status = gpmc_prefetch_status();
bytes = ((pref_status >> 24) & 0x7F);
ioread32_rep(info->nand_pref_fifo_add, p, bytes >> 2);
@@ -586,7 +585,8 @@ static void omap_read_buf_irq_pref(struct mtd_info *mtd, u_char *buf, int len)
init_completion(&info->comp);
/* configure and start prefetch transfer */
- ret = gpmc_prefetch_enable(info->gpmc_cs, 0x0, len, 0x0);
+ ret = gpmc_prefetch_enable(info->gpmc_cs,
+ PREFETCH_FIFOTHRESHOLD_READ, 0x0, len, 0x0);
if (ret)
/* PFPW engine is busy, use cpu copy methode */
goto out_copy;
@@ -630,7 +630,8 @@ static void omap_write_buf_irq_pref(struct mtd_info *mtd,
init_completion(&info->comp);
/* configure and start prefetch transfer */
- ret = gpmc_prefetch_enable(info->gpmc_cs, 0x0, len, 0x1);
+ ret = gpmc_prefetch_enable(info->gpmc_cs,
+ PREFETCH_FIFOTHRESHOLD_WRITE, 0x0, len, 0x1);
if (ret)
/* PFPW engine is busy, use cpu copy methode */
goto out_copy;
^ permalink raw reply related [flat|nested] 102+ messages in thread
* [PATCH 4/6] omap-3630 NAND: enable NAND io in prefetch-irq mode
[not found] <Sukumar Ghorai <s-ghorai@ti.com>
` (6 preceding siblings ...)
2010-04-16 11:35 ` [PATCH 3/6] OMAP NAND: configurable fifo threshold to gain the throughput Sukumar Ghorai
@ 2010-04-16 11:35 ` Sukumar Ghorai
2010-04-16 11:35 ` [PATCH 5/6] omap: NAND: ecc layout select from board file Sukumar Ghorai
` (7 subsequent siblings)
15 siblings, 0 replies; 102+ messages in thread
From: Sukumar Ghorai @ 2010-04-16 11:35 UTC (permalink / raw)
To: linux-mtd
Cc: sbranden, leochen, David.Woodhouse, linux-omap, tony,
vimal.newwork, Sukumar Ghorai
Update config file to enable NAND in prefetch IRQ mode for ZOOM3 and 3630SDP .
Signed-off-by: Sukumar Ghorai <s-ghorai@ti.com>
---
arch/arm/configs/omap_3630sdp_defconfig | 1 +
arch/arm/configs/omap_zoom3_defconfig | 1 +
2 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/arch/arm/configs/omap_3630sdp_defconfig b/arch/arm/configs/omap_3630sdp_defconfig
index a623927..9dfce1a
--- a/arch/arm/configs/omap_3630sdp_defconfig
+++ b/arch/arm/configs/omap_3630sdp_defconfig
@@ -525,6 +525,7 @@ CONFIG_MTD_NAND=y
CONFIG_MTD_NAND_OMAP2=y
CONFIG_MTD_NAND_OMAP_PREFETCH=y
# CONFIG_MTD_NAND_OMAP_PREFETCH_DMA is not set
+CONFIG_MTD_NAND_OMAP_PREFETCH_IRQ=y
CONFIG_MTD_NAND_IDS=y
# CONFIG_MTD_NAND_DISKONCHIP is not set
# CONFIG_MTD_NAND_NANDSIM is not set
diff --git a/arch/arm/configs/omap_zoom3_defconfig b/arch/arm/configs/omap_zoom3_defconfig
index 1a12e3e..27b16ed
--- a/arch/arm/configs/omap_zoom3_defconfig
+++ b/arch/arm/configs/omap_zoom3_defconfig
@@ -534,6 +534,7 @@ CONFIG_MTD_NAND=y
CONFIG_MTD_NAND_OMAP2=y
CONFIG_MTD_NAND_OMAP_PREFETCH=y
# CONFIG_MTD_NAND_OMAP_PREFETCH_DMA is not set
+CONFIG_MTD_NAND_OMAP_PREFETCH_IRQ=y
CONFIG_MTD_NAND_IDS=y
# CONFIG_MTD_NAND_DISKONCHIP is not set
# CONFIG_MTD_NAND_NANDSIM is not set
--
1.5.4.7
^ permalink raw reply related [flat|nested] 102+ messages in thread
* [PATCH 5/6] omap: NAND: ecc layout select from board file
[not found] <Sukumar Ghorai <s-ghorai@ti.com>
` (7 preceding siblings ...)
2010-04-16 11:35 ` [PATCH 4/6] omap-3630 NAND: enable NAND io in prefetch-irq mode Sukumar Ghorai
@ 2010-04-16 11:35 ` Sukumar Ghorai
2010-04-16 11:35 ` [PATCH 6/6] omap: NAND: Making ecc layout as compatible with romcode ecc Sukumar Ghorai
` (6 subsequent siblings)
15 siblings, 0 replies; 102+ messages in thread
From: Sukumar Ghorai @ 2010-04-16 11:35 UTC (permalink / raw)
To: linux-mtd
Cc: sbranden, leochen, David.Woodhouse, linux-omap, tony,
vimal.newwork, Sukumar Ghorai, Vimal Singh
This patch makes it possible to select sw or hw (different layout options)
ecc scheme supported by omap nand driver. And hw ecc layout selected for
sdp and zoom boards, by default.
Signed-off-by: Sukumar Ghorai <s-ghorai@ti.com>
Signed-off-by: Vimal Singh <vimalsingh@ti.com>
---
arch/arm/mach-omap2/board-sdp-flash.c | 1 +
arch/arm/mach-omap2/board-zoom-flash.c | 1 +
arch/arm/plat-omap/include/plat/nand.h | 4 ++++
drivers/mtd/nand/omap2.c | 28 ++++++++++++----------------
4 files changed, 18 insertions(+), 16 deletions(-)
diff --git a/arch/arm/mach-omap2/board-sdp-flash.c b/arch/arm/mach-omap2/board-sdp-flash.c
index 81b83ce..437a1a4
--- a/arch/arm/mach-omap2/board-sdp-flash.c
+++ b/arch/arm/mach-omap2/board-sdp-flash.c
@@ -162,6 +162,7 @@ __init board_nand_init(struct flash_partitions sdp_nand_parts, u8 cs)
sdp_nand_data.cs = cs;
sdp_nand_data.parts = sdp_nand_parts.parts;
sdp_nand_data.nr_parts = sdp_nand_parts.nr_parts;
+ sdp_nand_data.ecc_opt = 0x1; /* HW ECC in default layout */
if (cpu_is_omap3630())
sdp_nand_data.devsize = 1; /* 0: 8-bit, 1: 16-bit device */
diff --git a/arch/arm/mach-omap2/board-zoom-flash.c b/arch/arm/mach-omap2/board-zoom-flash.c
index 6a5dcf4..1547bdb
--- a/arch/arm/mach-omap2/board-zoom-flash.c
+++ b/arch/arm/mach-omap2/board-zoom-flash.c
@@ -71,6 +71,7 @@ void __init zoom_flash_init(struct flash_partitions zoom_nand_parts[], int cs)
zoom_nand_data.cs = cs;
zoom_nand_data.parts = zoom_nand_parts[0].parts;
zoom_nand_data.nr_parts = zoom_nand_parts[0].nr_parts;
+ zoom_nand_data.ecc_opt = 0x1; /* HW ECC in default layout */
zoom_nand_data.gpmc_baseaddr = (void *)(gpmc_base_add);
zoom_nand_data.gpmc_cs_baseaddr = (void *)(gpmc_base_add +
GPMC_CS0_BASE + cs * GPMC_CS_SIZE);
diff --git a/arch/arm/plat-omap/include/plat/nand.h b/arch/arm/plat-omap/include/plat/nand.h
index 8ba2e3e..b2ccd68
--- a/arch/arm/plat-omap/include/plat/nand.h
+++ b/arch/arm/plat-omap/include/plat/nand.h
@@ -25,6 +25,10 @@ struct omap_nand_platform_data {
void __iomem *gpmc_cs_baseaddr;
void __iomem *gpmc_baseaddr;
int devsize;
+ int ecc_opt; /* 0x0 - sw ecc
+ * 0x1 - hw ecc default ecc layout
+ * 0x2 - hw ecc in romcode layout
+ */
};
/* size (4 KiB) for IO mapping */
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 61c0c01..207fb3c
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -31,7 +31,6 @@
#define GPMC_BUF_FULL 0x00000001
#define GPMC_BUF_EMPTY 0x00000000
-#ifdef CONFIG_MTD_NAND_OMAP_HWECC
#define NAND_Ecc_P1e (1 << 0)
#define NAND_Ecc_P2e (1 << 1)
#define NAND_Ecc_P4e (1 << 2)
@@ -98,7 +97,6 @@
#define P4e_s(a) (TF(a & NAND_Ecc_P4e) << 0)
#define P4o_s(a) (TF(a & NAND_Ecc_P4o) << 1)
-#endif /* CONFIG_MTD_NAND_OMAP_HWECC */
#ifdef CONFIG_MTD_PARTITIONS
static const char *part_probes[] = { "cmdlinepart", NULL };
@@ -673,7 +671,6 @@ static int omap_verify_buf(struct mtd_info *mtd, const u_char * buf, int len)
return 0;
}
-#ifdef CONFIG_MTD_NAND_OMAP_HWECC
/**
* omap_hwecc_init - Initialize the HW ECC for NAND flash in GPMC controller
* @mtd: MTD device structure
@@ -951,7 +948,6 @@ static void omap_enable_hwecc(struct mtd_info *mtd, int mode)
__raw_writel(val, info->gpmc_baseaddr + GPMC_ECC_CONFIG);
}
-#endif
/**
* omap_wait - wait until the command is done
@@ -1139,19 +1135,19 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
}
info->nand.verify_buf = omap_verify_buf;
-#ifdef CONFIG_MTD_NAND_OMAP_HWECC
- info->nand.ecc.bytes = 3;
- info->nand.ecc.size = 512;
- info->nand.ecc.calculate = omap_calculate_ecc;
- info->nand.ecc.hwctl = omap_enable_hwecc;
- info->nand.ecc.correct = omap_correct_data;
- info->nand.ecc.mode = NAND_ECC_HW;
+ if (pdata->ecc_opt & 0x3) {
+ info->nand.ecc.bytes = 3;
+ info->nand.ecc.size = 512;
+ info->nand.ecc.calculate = omap_calculate_ecc;
+ info->nand.ecc.hwctl = omap_enable_hwecc;
+ info->nand.ecc.correct = omap_correct_data;
+ info->nand.ecc.mode = NAND_ECC_HW;
- /* init HW ECC */
- omap_hwecc_init(&info->mtd);
-#else
- info->nand.ecc.mode = NAND_ECC_SOFT;
-#endif
+ /* init HW ECC */
+ omap_hwecc_init(&info->mtd);
+ } else {
+ info->nand.ecc.mode = NAND_ECC_SOFT;
+ }
/* DIP switches on some boards change between 8 and 16 bit
* bus widths for flash. Try the other width if the first try fails.
^ permalink raw reply related [flat|nested] 102+ messages in thread
* [PATCH 6/6] omap: NAND: Making ecc layout as compatible with romcode ecc
[not found] <Sukumar Ghorai <s-ghorai@ti.com>
` (8 preceding siblings ...)
2010-04-16 11:35 ` [PATCH 5/6] omap: NAND: ecc layout select from board file Sukumar Ghorai
@ 2010-04-16 11:35 ` Sukumar Ghorai
2010-05-12 9:48 ` [PATCH 0/3] omap3 nand: cleanup exiting platform related code Sukumar Ghorai
` (5 subsequent siblings)
15 siblings, 0 replies; 102+ messages in thread
From: Sukumar Ghorai @ 2010-04-16 11:35 UTC (permalink / raw)
To: linux-mtd
Cc: sbranden, leochen, David.Woodhouse, linux-omap, tony,
vimal.newwork, Sukumar Ghorai
This patch overrides nand ecc layout and bad block descriptor (for 8-bit
device) to support hw ecc in romcode layout. So as to have in sync with ecc
layout throughout; i.e. x-laod, u-boot and kernel.
This patch also enables to use romcode ecc for spd and zoom, by default.
This enables to flash x-load, u-boot, kernel, FS images from kernel itself
and compatiable with other tools.
Signed-off-by: Sukumar Ghorai <s-ghorai@ti.com>
---
arch/arm/mach-omap2/board-sdp-flash.c | 2 +-
arch/arm/mach-omap2/board-zoom-flash.c | 2 +-
drivers/mtd/nand/omap2.c | 42 ++++++++++++++++++++++++++++++++
3 files changed, 44 insertions(+), 2 deletions(-)
diff --git a/arch/arm/mach-omap2/board-sdp-flash.c b/arch/arm/mach-omap2/board-sdp-flash.c
index 437a1a4..ac891ea
--- a/arch/arm/mach-omap2/board-sdp-flash.c
+++ b/arch/arm/mach-omap2/board-sdp-flash.c
@@ -162,7 +162,7 @@ __init board_nand_init(struct flash_partitions sdp_nand_parts, u8 cs)
sdp_nand_data.cs = cs;
sdp_nand_data.parts = sdp_nand_parts.parts;
sdp_nand_data.nr_parts = sdp_nand_parts.nr_parts;
- sdp_nand_data.ecc_opt = 0x1; /* HW ECC in default layout */
+ sdp_nand_data.ecc_opt = 0x2; /* HW ECC layout as in ROMCODE */
if (cpu_is_omap3630())
sdp_nand_data.devsize = 1; /* 0: 8-bit, 1: 16-bit device */
diff --git a/arch/arm/mach-omap2/board-zoom-flash.c b/arch/arm/mach-omap2/board-zoom-flash.c
index 1547bdb..53eeaa6
--- a/arch/arm/mach-omap2/board-zoom-flash.c
+++ b/arch/arm/mach-omap2/board-zoom-flash.c
@@ -71,7 +71,7 @@ void __init zoom_flash_init(struct flash_partitions zoom_nand_parts[], int cs)
zoom_nand_data.cs = cs;
zoom_nand_data.parts = zoom_nand_parts[0].parts;
zoom_nand_data.nr_parts = zoom_nand_parts[0].nr_parts;
- zoom_nand_data.ecc_opt = 0x1; /* HW ECC in default layout */
+ zoom_nand_data.ecc_opt = 0x2; /* HW ECC in romcode layout */
zoom_nand_data.gpmc_baseaddr = (void *)(gpmc_base_add);
zoom_nand_data.gpmc_cs_baseaddr = (void *)(gpmc_base_add +
GPMC_CS0_BASE + cs * GPMC_CS_SIZE);
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 207fb3c..f5d2c53
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -152,6 +152,39 @@ struct omap_nand_info {
u_char *buf;
};
+static struct nand_ecclayout hw_x8_romcode_oob_64 = {
+ .eccbytes = 12,
+ .eccpos = {
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
+ },
+ .oobfree = {
+ {.offset = 13,
+ .length = 51}
+ }
+};
+
+/* Define some generic bad / good block scan pattern which are used
+ * while scanning a device for factory marked good / bad blocks
+ */
+static uint8_t scan_ff_pattern[] = { 0xff };
+static struct nand_bbt_descr bb_descrip_flashbased = {
+ .options = NAND_BBT_SCANEMPTY | NAND_BBT_SCANALLPAGES,
+ .offs = 0,
+ .len = 1,
+ .pattern = scan_ff_pattern,
+};
+
+static struct nand_ecclayout hw_x16_romcode_oob_64 = {
+ .eccbytes = 12,
+ .eccpos = {
+ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13
+ },
+ .oobfree = {
+ {.offset = 14,
+ .length = 50}
+ }
+};
+
/**
* omap_nand_wp - This function enable or disable the Write Protect feature
* @mtd: MTD device structure
@@ -1136,6 +1169,15 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
info->nand.verify_buf = omap_verify_buf;
if (pdata->ecc_opt & 0x3) {
+ if (pdata->ecc_opt == 0x2) {
+ if (info->nand.options & NAND_BUSWIDTH_16) {
+ info->nand.ecc.layout = &hw_x16_romcode_oob_64;
+ } else {
+ info->nand.ecc.layout = &hw_x8_romcode_oob_64;
+ info->nand.badblock_pattern =
+ &bb_descrip_flashbased;
+ }
+ }
info->nand.ecc.bytes = 3;
info->nand.ecc.size = 512;
info->nand.ecc.calculate = omap_calculate_ecc;
^ permalink raw reply related [flat|nested] 102+ messages in thread
* Re: [PATCH 3/6] OMAP NAND: configurable fifo threshold to gain the throughput
2010-04-16 11:35 ` [PATCH 3/6] OMAP NAND: configurable fifo threshold to gain the throughput Sukumar Ghorai
@ 2010-04-16 12:45 ` Vimal Singh
0 siblings, 0 replies; 102+ messages in thread
From: Vimal Singh @ 2010-04-16 12:45 UTC (permalink / raw)
To: Sukumar Ghorai
Cc: linux-mtd, sbranden, leochen, David.Woodhouse, linux-omap, tony,
Vimal Singh
Hi Ghorai,
On Fri, Apr 16, 2010 at 5:05 PM, Sukumar Ghorai <s-ghorai@ti.com> wrote:
[...]
> - ret = gpmc_prefetch_enable(info->gpmc_cs, 0x0, len, 0x0);
> + ret = gpmc_prefetch_enable(info->gpmc_cs, 0x40, 0x0, len, 0x0);
Use macros here too then.
> if (ret) {
> /* PFPW engine is busy, use cpu copy method */
> if (info->nand.options & NAND_BUSWIDTH_16)
> @@ -354,7 +354,7 @@ static void omap_write_buf_pref(struct mtd_info *mtd,
> }
>
> /* configure and start prefetch transfer */
> - ret = gpmc_prefetch_enable(info->gpmc_cs, 0x0, len, 0x1);
> + ret = gpmc_prefetch_enable(info->gpmc_cs, 0x40, 0x0, len, 0x1);
here too
> if (ret) {
> /* PFPW engine is busy, use cpu copy method */
> if (info->nand.options & NAND_BUSWIDTH_16)
> @@ -405,10 +405,11 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr,
> dma_addr_t dma_addr;
> int ret;
>
> - /* The fifo depth is 64 bytes. We have a sync at each frame and frame
> - * length is 64 bytes.
> + /* The fifo depth is 64 bytes max.
> + * But configure the FIFO-threahold to 32 to get a sync at each frame
> + * and frame length is 32 bytes.
> */
> - int buf_len = len >> 6;
> + int buf_len = len >> 5;
>
> if (addr >= high_memory) {
> struct page *p1;
> @@ -447,7 +448,7 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr,
> OMAP24XX_DMA_GPMC, OMAP_DMA_SRC_SYNC);
> }
> /* configure and start prefetch transfer */
> - ret = gpmc_prefetch_enable(info->gpmc_cs, 0x1, len, is_write);
> + ret = gpmc_prefetch_enable(info->gpmc_cs, 0x20, 0x1, len, is_write);
> if (ret)
> /* PFPW engine is busy, use cpu copy methode */
> goto out_copy;
> @@ -524,6 +525,7 @@ static void omap_write_buf_dma_pref(struct mtd_info *mtd,
> static irqreturn_t omap_nand_irq(int this_irq, void *dev)
> {
> struct omap_nand_info *info = (struct omap_nand_info *) dev;
> + u32 *p = (u32 *) info->buf;
> u32 irq_enb = 0, pref_status = 0, bytes = 0;
> u32 irq_stats = __raw_readl(info->gpmc_baseaddr + GPMC_IRQSTATUS);
> u32 pref_config = __raw_readl(info->gpmc_baseaddr +
> @@ -533,14 +535,11 @@ static irqreturn_t omap_nand_irq(int this_irq, void *dev)
> if (irq_stats & 0x2)
> goto done;
>
> - u32 *p = (u32 *) info->buf;
> - pref_status = gpmc_prefetch_status();
> - bytes = ((pref_status >> 24) & 0x7F);
> + bytes = PREFETCH_FIFOTHRESHOLD_WRITE;
By this, you are not really keeping prefetch the busyest.
you are filling only 'PREFETCH_FIFOTHRESHOLD_WRITE' bytes, while there
could be more free spaces.
Previous way of doing it was more efficent.
> iowrite32_rep(info->nand_pref_fifo_add, p, bytes >> 2);
> info->buf = info->buf + bytes;
>
> } else {
> - u32 *p = (u32 *) info->buf;
> pref_status = gpmc_prefetch_status();
> bytes = ((pref_status >> 24) & 0x7F);
> ioread32_rep(info->nand_pref_fifo_add, p, bytes >> 2);
> @@ -586,7 +585,8 @@ static void omap_read_buf_irq_pref(struct mtd_info *mtd, u_char *buf, int len)
> init_completion(&info->comp);
>
> /* configure and start prefetch transfer */
> - ret = gpmc_prefetch_enable(info->gpmc_cs, 0x0, len, 0x0);
> + ret = gpmc_prefetch_enable(info->gpmc_cs,
> + PREFETCH_FIFOTHRESHOLD_READ, 0x0, len, 0x0);
> if (ret)
> /* PFPW engine is busy, use cpu copy methode */
> goto out_copy;
> @@ -630,7 +630,8 @@ static void omap_write_buf_irq_pref(struct mtd_info *mtd,
> init_completion(&info->comp);
>
> /* configure and start prefetch transfer */
> - ret = gpmc_prefetch_enable(info->gpmc_cs, 0x0, len, 0x1);
> + ret = gpmc_prefetch_enable(info->gpmc_cs,
> + PREFETCH_FIFOTHRESHOLD_WRITE, 0x0, len, 0x1);
In case of write, in my experiments, fifo thresholed '24' was the best
compromise for throughput and cpu load.
Regards,
Vimal
^ permalink raw reply [flat|nested] 102+ messages in thread
* RE: [PATCH] nand support on omap3 boards
2010-04-13 17:37 ` [PATCH] nand support on omap3 boards Sukumar Ghorai
2010-04-13 17:37 ` [PATCH v3 1/8] omap3: zoom: Introducing 'board-zoom-flash.c' Sukumar Ghorai
@ 2010-05-04 6:00 ` Ghorai, Sukumar
2010-05-04 6:01 ` Ghorai, Sukumar
2010-05-28 13:48 ` Ghorai, Sukumar
3 siblings, 0 replies; 102+ messages in thread
From: Ghorai, Sukumar @ 2010-05-04 6:00 UTC (permalink / raw)
To: Tony Lindgren; +Cc: linux-omap@vger.kernel.org
Tony,
Would you please check if there are no further comments and could you pull them in?
1/8: https://patchwork.kernel.org/patch/92220/
2/8: https://patchwork.kernel.org/patch/92232/
3/8: https://patchwork.kernel.org/patch/92221/
4/8: https://patchwork.kernel.org/patch/92230/
5/8: https://patchwork.kernel.org/patch/92224/
6/8: https://patchwork.kernel.org/patch/92222/
7/8: https://patchwork.kernel.org/patch/92223/
8/8: https://patchwork.kernel.org/patch/92229/
Regards,
Nishanth Menon
> -----Original Message-----
> From: Ghorai, Sukumar
> Sent: 2010-04-13 23:07
> To: linux-omap@vger.kernel.org
> Cc: Ghorai, Sukumar
> Subject: [PATCH] nand support on omap3 boards
>
> The following set of patches applies on top of the Tony's master
> branch.
> And these are the patches required to enable nand (nor and onenand for
> sdp
> only) for different platform.
>
> Sukumar Ghorai (3):
> OMAP: ZOOM: Introducing 'board-zoom-flash.c'
> omap3: add support for NAND on zoom2 board
> omap3: add support for NAND on zoom3 board
> omap-3630-sdp : Add support for Flash
> omap-3630-sdp: enable Flash device support
> omap3: add support for NAND on LDP board
> zoom2: enable NAND support
> zoom3: enable NAND support
>
> arch/arm/configs/omap_3630sdp_defconfig | 77 +++++++++++++++++-
> arch/arm/configs/omap_zoom2_defconfig | 90
> ++++++++++++++++++++-
> arch/arm/configs/omap_zoom3_defconfig | 90
> ++++++++++++++++++++-
> arch/arm/mach-omap2/Makefile | 4 +
> arch/arm/mach-omap2/board-3630sdp.c | 110
> +++++++++++++++++++++++++
> arch/arm/mach-omap2/board-ldp.c | 41 +++++++++
> arch/arm/mach-omap2/board-sdp-flash.c | 2 +
> arch/arm/mach-omap2/board-zoom-flash.c | 82 ++++++++++++++++++
> arch/arm/mach-omap2/board-zoom2.c | 49 +++++++++++
> arch/arm/mach-omap2/board-zoom3.c | 48 +++++++++++
> arch/arm/mach-omap2/include/mach/board-zoom.h | 11 +++
> 11 files changed, 601 insertions(+), 3 deletions(-) create mode 100644
> arch/arm/mach-omap2/board-zoom-flash.c
^ permalink raw reply [flat|nested] 102+ messages in thread
* RE: [PATCH] nand support on omap3 boards
2010-04-13 17:37 ` [PATCH] nand support on omap3 boards Sukumar Ghorai
2010-04-13 17:37 ` [PATCH v3 1/8] omap3: zoom: Introducing 'board-zoom-flash.c' Sukumar Ghorai
2010-05-04 6:00 ` Ghorai, Sukumar
@ 2010-05-04 6:01 ` Ghorai, Sukumar
2010-05-28 13:48 ` Ghorai, Sukumar
3 siblings, 0 replies; 102+ messages in thread
From: Ghorai, Sukumar @ 2010-05-04 6:01 UTC (permalink / raw)
To: Tony Lindgren; +Cc: linux-omap@vger.kernel.org
Tony,
Would you please check if there are no further comments and could you pull them in?
1/8: https://patchwork.kernel.org/patch/92220/
2/8: https://patchwork.kernel.org/patch/92232/
3/8: https://patchwork.kernel.org/patch/92221/
4/8: https://patchwork.kernel.org/patch/92230/
5/8: https://patchwork.kernel.org/patch/92224/
6/8: https://patchwork.kernel.org/patch/92222/
7/8: https://patchwork.kernel.org/patch/92223/
8/8: https://patchwork.kernel.org/patch/92229/
Regards,
Sukumar Ghorai
> -----Original Message-----
> From: Ghorai, Sukumar
> Sent: 2010-04-13 23:07
> To: linux-omap@vger.kernel.org
> Cc: Ghorai, Sukumar
> Subject: [PATCH] nand support on omap3 boards
>
> The following set of patches applies on top of the Tony's master
> branch.
> And these are the patches required to enable nand (nor and onenand for
> sdp
> only) for different platform.
>
> Sukumar Ghorai (3):
> OMAP: ZOOM: Introducing 'board-zoom-flash.c'
> omap3: add support for NAND on zoom2 board
> omap3: add support for NAND on zoom3 board
> omap-3630-sdp : Add support for Flash
> omap-3630-sdp: enable Flash device support
> omap3: add support for NAND on LDP board
> zoom2: enable NAND support
> zoom3: enable NAND support
>
> arch/arm/configs/omap_3630sdp_defconfig | 77 +++++++++++++++++-
> arch/arm/configs/omap_zoom2_defconfig | 90
> ++++++++++++++++++++-
> arch/arm/configs/omap_zoom3_defconfig | 90
> ++++++++++++++++++++-
> arch/arm/mach-omap2/Makefile | 4 +
> arch/arm/mach-omap2/board-3630sdp.c | 110
> +++++++++++++++++++++++++
> arch/arm/mach-omap2/board-ldp.c | 41 +++++++++
> arch/arm/mach-omap2/board-sdp-flash.c | 2 +
> arch/arm/mach-omap2/board-zoom-flash.c | 82 ++++++++++++++++++
> arch/arm/mach-omap2/board-zoom2.c | 49 +++++++++++
> arch/arm/mach-omap2/board-zoom3.c | 48 +++++++++++
> arch/arm/mach-omap2/include/mach/board-zoom.h | 11 +++
> 11 files changed, 601 insertions(+), 3 deletions(-) create mode 100644
> arch/arm/mach-omap2/board-zoom-flash.c
^ permalink raw reply [flat|nested] 102+ messages in thread
* [PATCH 0/3] omap3 nand: cleanup exiting platform related code
[not found] <Sukumar Ghorai <s-ghorai@ti.com>
` (9 preceding siblings ...)
2010-04-16 11:35 ` [PATCH 6/6] omap: NAND: Making ecc layout as compatible with romcode ecc Sukumar Ghorai
@ 2010-05-12 9:48 ` Sukumar Ghorai
2010-05-12 9:48 ` [PATCH 1/3] omap3: GPMC register definition at common location Sukumar Ghorai
2010-05-13 15:44 ` [PATCH 0/3] omap3 nand: cleanup exiting platform related code Tony Lindgren
2010-05-14 15:23 ` [PATCH v2 0/2] " Sukumar Ghorai
` (4 subsequent siblings)
15 siblings, 2 replies; 102+ messages in thread
From: Sukumar Ghorai @ 2010-05-12 9:48 UTC (permalink / raw)
To: linux-omap
Cc: linux-mtd, tony, sakoman, mike, Artem.Bityutskiy, Sukumar Ghorai
The following set of patches applies on top of master branch.
http://git.kernel.org/?p=linux/kernel/git/tmlind/linux-omap-2.6.git
Patches verified on: omap3430-SDP, omap3630-sdp, zoom3 and beagle board
And these are the patches required to address the following input -
1. The NAND driver needs to stop tinkering with the GPMC registers
The omap General Purpose Memory Controller (GPMC) registers are omap
specific, and not driver specific. Tinkering with these registers can
cause issues with the other devices on the GPMC.
2. Passing hardcoded GPMC_CS0_BASE needs to go from the board files
Passing hardcoded GPMC virtual addressess is sure way to mess up things.
This should all become unnecessary once the NAND drivers stops messing
with the GPMC registers directly.
Sukumar Ghorai (3):
omap3: GPMC register definition at common location
omap3 nand: cleanup for not to use GPMC virtual address
omap3 nand: fix issue in board file to detect the nand
arch/arm/mach-omap2/board-cm-t35.c | 20 +----
arch/arm/mach-omap2/board-devkit8000.c | 25 +------
arch/arm/mach-omap2/board-omap3beagle.c | 24 +-----
arch/arm/mach-omap2/board-omap3touchbook.c | 25 +------
arch/arm/mach-omap2/board-overo.c | 24 +-----
arch/arm/mach-omap2/gpmc.c | 67 +++++-----------
arch/arm/plat-omap/include/plat/gpmc.h | 41 ++++++++-
arch/arm/plat-omap/include/plat/nand.h | 6 +-
drivers/mtd/nand/omap2.c | 125 ++++++++++------------------
9 files changed, 109 insertions(+), 248 deletions(-)
^ permalink raw reply [flat|nested] 102+ messages in thread
* [PATCH 1/3] omap3: GPMC register definition at common location
2010-05-12 9:48 ` [PATCH 0/3] omap3 nand: cleanup exiting platform related code Sukumar Ghorai
@ 2010-05-12 9:48 ` Sukumar Ghorai
2010-05-12 9:48 ` [PATCH 2/3] omap3 nand: cleanup for not to use GPMC virtual address Sukumar Ghorai
` (2 more replies)
2010-05-13 15:44 ` [PATCH 0/3] omap3 nand: cleanup exiting platform related code Tony Lindgren
1 sibling, 3 replies; 102+ messages in thread
From: Sukumar Ghorai @ 2010-05-12 9:48 UTC (permalink / raw)
To: linux-omap
Cc: linux-mtd, tony, sakoman, mike, Artem.Bityutskiy, Sukumar Ghorai
GPMC register definition move to common place in gpmc.h.
Signed-off-by: Sukumar Ghorai <s-ghorai@ti.com>
---
arch/arm/mach-omap2/gpmc.c | 38 +------------------------------
arch/arm/plat-omap/include/plat/gpmc.h | 36 +++++++++++++++++++++++++++--
drivers/mtd/nand/omap2.c | 14 ++++-------
3 files changed, 40 insertions(+), 48 deletions(-)
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index 5bc3ca0..9c77af0
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -28,40 +28,6 @@
#include <plat/sdrc.h>
-/* GPMC register offsets */
-#define GPMC_REVISION 0x00
-#define GPMC_SYSCONFIG 0x10
-#define GPMC_SYSSTATUS 0x14
-#define GPMC_IRQSTATUS 0x18
-#define GPMC_IRQENABLE 0x1c
-#define GPMC_TIMEOUT_CONTROL 0x40
-#define GPMC_ERR_ADDRESS 0x44
-#define GPMC_ERR_TYPE 0x48
-#define GPMC_CONFIG 0x50
-#define GPMC_STATUS 0x54
-#define GPMC_PREFETCH_CONFIG1 0x1e0
-#define GPMC_PREFETCH_CONFIG2 0x1e4
-#define GPMC_PREFETCH_CONTROL 0x1ec
-#define GPMC_PREFETCH_STATUS 0x1f0
-#define GPMC_ECC_CONFIG 0x1f4
-#define GPMC_ECC_CONTROL 0x1f8
-#define GPMC_ECC_SIZE_CONFIG 0x1fc
-
-#define GPMC_CS0 0x60
-#define GPMC_CS_SIZE 0x30
-
-#define GPMC_MEM_START 0x00000000
-#define GPMC_MEM_END 0x3FFFFFFF
-#define BOOT_ROM_SPACE 0x100000 /* 1MB */
-
-#define GPMC_CHUNK_SHIFT 24 /* 16 MB */
-#define GPMC_SECTION_SHIFT 28 /* 128 MB */
-
-#define PREFETCH_FIFOTHRESHOLD (0x40 << 8)
-#define CS_NUM_SHIFT 24
-#define ENABLE_PREFETCH (0x1 << 7)
-#define DMA_MPU_MODE 2
-
/* Structure to save gpmc cs context */
struct gpmc_cs_config {
u32 config1;
@@ -112,7 +78,7 @@ void gpmc_cs_write_reg(int cs, int idx, u32 val)
{
void __iomem *reg_addr;
- reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx;
+ reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx;
__raw_writel(val, reg_addr);
}
@@ -120,7 +86,7 @@ u32 gpmc_cs_read_reg(int cs, int idx)
{
void __iomem *reg_addr;
- reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx;
+ reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx;
return __raw_readl(reg_addr);
}
diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h
index 145838a..347d212 100644
--- a/arch/arm/plat-omap/include/plat/gpmc.h
+++ b/arch/arm/plat-omap/include/plat/gpmc.h
@@ -25,10 +25,40 @@
#define GPMC_CS_NAND_ADDRESS 0x20
#define GPMC_CS_NAND_DATA 0x24
-#define GPMC_CONFIG 0x50
-#define GPMC_STATUS 0x54
+/* GPMC register offsets */
+#define GPMC_REVISION 0x00
+#define GPMC_SYSCONFIG 0x10
+#define GPMC_SYSSTATUS 0x14
+#define GPMC_IRQSTATUS 0x18
+#define GPMC_IRQENABLE 0x1c
+#define GPMC_TIMEOUT_CONTROL 0x40
+#define GPMC_ERR_ADDRESS 0x44
+#define GPMC_ERR_TYPE 0x48
+#define GPMC_CONFIG 0x50
+#define GPMC_STATUS 0x54
+#define GPMC_PREFETCH_CONFIG1 0x1e0
+#define GPMC_PREFETCH_CONFIG2 0x1e4
+#define GPMC_PREFETCH_CONTROL 0x1ec
+#define GPMC_PREFETCH_STATUS 0x1f0
+#define GPMC_ECC_CONFIG 0x1f4
+#define GPMC_ECC_CONTROL 0x1f8
+#define GPMC_ECC_SIZE_CONFIG 0x1fc
+#define GPMC_ECC1_RESULT 0x200
+
#define GPMC_CS0_BASE 0x60
-#define GPMC_CS_SIZE 0x30
+#define GPMC_CS_SIZE 0x30
+
+#define GPMC_MEM_START 0x00000000
+#define GPMC_MEM_END 0x3FFFFFFF
+#define BOOT_ROM_SPACE 0x100000 /* 1MB */
+
+#define GPMC_CHUNK_SHIFT 24 /* 16 MB */
+#define GPMC_SECTION_SHIFT 28 /* 128 MB */
+
+#define PREFETCH_FIFOTHRESHOLD (0x40 << 8)
+#define CS_NUM_SHIFT 24
+#define ENABLE_PREFETCH (0x1 << 7)
+#define DMA_MPU_MODE 2
#define GPMC_CONFIG1_WRAPBURST_SUPP (1 << 31)
#define GPMC_CONFIG1_READMULTIPLE_SUPP (1 << 30)
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 7545568..258bf06
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -23,12 +23,6 @@
#include <plat/gpmc.h>
#include <plat/nand.h>
-#define GPMC_IRQ_STATUS 0x18
-#define GPMC_ECC_CONFIG 0x1F4
-#define GPMC_ECC_CONTROL 0x1F8
-#define GPMC_ECC_SIZE_CONFIG 0x1FC
-#define GPMC_ECC1_RESULT 0x200
-
#define DRIVER_NAME "omap2-nand"
#define NAND_WP_OFF 0
@@ -37,6 +31,7 @@
#define GPMC_BUF_FULL 0x00000001
#define GPMC_BUF_EMPTY 0x00000000
+#ifdef CONFIG_MTD_NAND_OMAP_HWECC
#define NAND_Ecc_P1e (1 << 0)
#define NAND_Ecc_P2e (1 << 1)
#define NAND_Ecc_P4e (1 << 2)
@@ -103,6 +98,7 @@
#define P4e_s(a) (TF(a & NAND_Ecc_P4e) << 0)
#define P4o_s(a) (TF(a & NAND_Ecc_P4o) << 1)
+#endif /* CONFIG_MTD_NAND_OMAP_HWECC */
#ifdef CONFIG_MTD_PARTITIONS
static const char *part_probes[] = { "cmdlinepart", NULL };
@@ -854,20 +850,20 @@ static int omap_dev_ready(struct mtd_info *mtd)
{
struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
mtd);
- unsigned int val = __raw_readl(info->gpmc_baseaddr + GPMC_IRQ_STATUS);
+ unsigned int val = __raw_readl(info->gpmc_baseaddr + GPMC_IRQSTATUS);
if ((val & 0x100) == 0x100) {
/* Clear IRQ Interrupt */
val |= 0x100;
val &= ~(0x0);
- __raw_writel(val, info->gpmc_baseaddr + GPMC_IRQ_STATUS);
+ __raw_writel(val, info->gpmc_baseaddr + GPMC_IRQSTATUS);
} else {
unsigned int cnt = 0;
while (cnt++ < 0x1FF) {
if ((val & 0x100) == 0x100)
return 0;
val = __raw_readl(info->gpmc_baseaddr +
- GPMC_IRQ_STATUS);
+ GPMC_IRQSTATUS);
}
}
^ permalink raw reply related [flat|nested] 102+ messages in thread
* [PATCH 2/3] omap3 nand: cleanup for not to use GPMC virtual address
2010-05-12 9:48 ` [PATCH 1/3] omap3: GPMC register definition at common location Sukumar Ghorai
@ 2010-05-12 9:48 ` Sukumar Ghorai
2010-05-12 9:48 ` [PATCH 3/3] omap3 nand: fix issue in board file to detect the nand Sukumar Ghorai
2010-05-13 15:41 ` [PATCH 2/3] omap3 nand: cleanup for not to use GPMC virtual address Tony Lindgren
2010-05-13 6:15 ` [PATCH 1/3] omap3: GPMC register definition at common location Mike Rapoport
2010-05-13 15:41 ` Tony Lindgren
2 siblings, 2 replies; 102+ messages in thread
From: Sukumar Ghorai @ 2010-05-12 9:48 UTC (permalink / raw)
To: linux-omap
Cc: linux-mtd, tony, sakoman, mike, Artem.Bityutskiy, Sukumar Ghorai
Necessary function added in GPMC module and used by nand driver. This is for
not to use GPMC address directly from nand driver. Also it was passing GPMC
base address from board files and that is removed.
Signed-off-by: Sukumar Ghorai <s-ghorai@ti.com>
---
arch/arm/mach-omap2/board-cm-t35.c | 4 -
arch/arm/mach-omap2/board-devkit8000.c | 9 --
arch/arm/mach-omap2/board-omap3beagle.c | 8 --
arch/arm/mach-omap2/board-omap3touchbook.c | 9 --
arch/arm/mach-omap2/board-overo.c | 7 --
arch/arm/mach-omap2/gpmc.c | 29 ++++---
arch/arm/plat-omap/include/plat/gpmc.h | 5 +-
arch/arm/plat-omap/include/plat/nand.h | 6 +-
drivers/mtd/nand/omap2.c | 117 ++++++++++-----------------
9 files changed, 67 insertions(+), 127 deletions(-)
diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c
index e679a2c..fb23122
--- a/arch/arm/mach-omap2/board-cm-t35.c
+++ b/arch/arm/mach-omap2/board-cm-t35.c
@@ -61,8 +61,6 @@
#define SB_T35_SMSC911X_GPIO 65
#define NAND_BLOCK_SIZE SZ_128K
-#define GPMC_CS0_BASE 0x60
-#define GPMC_CS0_BASE_ADDR (OMAP34XX_GPMC_VIRT + GPMC_CS0_BASE)
#if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
#include <linux/smsc911x.h>
@@ -223,8 +221,6 @@ static struct omap_nand_platform_data cm_t35_nand_data = {
.nr_parts = ARRAY_SIZE(cm_t35_nand_partitions),
.dma_channel = -1, /* disable DMA in OMAP NAND driver */
.cs = 0,
- .gpmc_cs_baseaddr = (void __iomem *)GPMC_CS0_BASE_ADDR,
- .gpmc_baseaddr = (void __iomem *)OMAP34XX_GPMC_VIRT,
};
diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c
index 47e3af2..be50d18
--- a/arch/arm/mach-omap2/board-devkit8000.c
+++ b/arch/arm/mach-omap2/board-devkit8000.c
@@ -58,9 +58,6 @@
#include "mux.h"
#include "hsmmc.h"
-#define GPMC_CS0_BASE 0x60
-#define GPMC_CS_SIZE 0x30
-
#define NAND_BLOCK_SIZE SZ_128K
#define OMAP_DM9000_GPIO_IRQ 25
@@ -581,8 +578,6 @@ static void __init devkit8000_flash_init(void)
u8 cs = 0;
u8 nandcs = GPMC_CS_NUM + 1;
- u32 gpmc_base_add = OMAP34XX_GPMC_VIRT;
-
/* find out the chip-select on which NAND exists */
while (cs < GPMC_CS_NUM) {
u32 ret = 0;
@@ -604,10 +599,6 @@ static void __init devkit8000_flash_init(void)
if (nandcs < GPMC_CS_NUM) {
devkit8000_nand_data.cs = nandcs;
- devkit8000_nand_data.gpmc_cs_baseaddr = (void *)
- (gpmc_base_add + GPMC_CS0_BASE + nandcs * GPMC_CS_SIZE);
- devkit8000_nand_data.gpmc_baseaddr = (void *)
- (gpmc_base_add);
printk(KERN_INFO "Registering NAND on CS%d\n", nandcs);
if (platform_device_register(&devkit8000_nand_device) < 0)
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index 962d377..becaebe
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -47,9 +47,6 @@
#include "mux.h"
#include "hsmmc.h"
-#define GPMC_CS0_BASE 0x60
-#define GPMC_CS_SIZE 0x30
-
#define NAND_BLOCK_SIZE SZ_128K
static struct mtd_partition omap3beagle_nand_partitions[] = {
@@ -377,8 +374,6 @@ static void __init omap3beagle_flash_init(void)
u8 cs = 0;
u8 nandcs = GPMC_CS_NUM + 1;
- u32 gpmc_base_add = OMAP34XX_GPMC_VIRT;
-
/* find out the chip-select on which NAND exists */
while (cs < GPMC_CS_NUM) {
u32 ret = 0;
@@ -400,9 +395,6 @@ static void __init omap3beagle_flash_init(void)
if (nandcs < GPMC_CS_NUM) {
omap3beagle_nand_data.cs = nandcs;
- omap3beagle_nand_data.gpmc_cs_baseaddr = (void *)
- (gpmc_base_add + GPMC_CS0_BASE + nandcs * GPMC_CS_SIZE);
- omap3beagle_nand_data.gpmc_baseaddr = (void *) (gpmc_base_add);
printk(KERN_INFO "Registering NAND on CS%d\n", nandcs);
if (platform_device_register(&omap3beagle_nand_device) < 0)
diff --git a/arch/arm/mach-omap2/board-omap3touchbook.c b/arch/arm/mach-omap2/board-omap3touchbook.c
index 2504d41..d6f1b12
--- a/arch/arm/mach-omap2/board-omap3touchbook.c
+++ b/arch/arm/mach-omap2/board-omap3touchbook.c
@@ -54,9 +54,6 @@
#include <asm/setup.h>
-#define GPMC_CS0_BASE 0x60
-#define GPMC_CS_SIZE 0x30
-
#define NAND_BLOCK_SIZE SZ_128K
#define OMAP3_AC_GPIO 136
@@ -459,8 +456,6 @@ static void __init omap3touchbook_flash_init(void)
u8 cs = 0;
u8 nandcs = GPMC_CS_NUM + 1;
- u32 gpmc_base_add = OMAP34XX_GPMC_VIRT;
-
/* find out the chip-select on which NAND exists */
while (cs < GPMC_CS_NUM) {
u32 ret = 0;
@@ -482,10 +477,6 @@ static void __init omap3touchbook_flash_init(void)
if (nandcs < GPMC_CS_NUM) {
omap3touchbook_nand_data.cs = nandcs;
- omap3touchbook_nand_data.gpmc_cs_baseaddr = (void *)
- (gpmc_base_add + GPMC_CS0_BASE + nandcs * GPMC_CS_SIZE);
- omap3touchbook_nand_data.gpmc_baseaddr =
- (void *) (gpmc_base_add);
printk(KERN_INFO "Registering NAND on CS%d\n", nandcs);
if (platform_device_register(&omap3touchbook_nand_device) < 0)
diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
index 8848c7c..d843a0a
--- a/arch/arm/mach-omap2/board-overo.c
+++ b/arch/arm/mach-omap2/board-overo.c
@@ -58,8 +58,6 @@
#define OVERO_GPIO_USBH_NRESET 183
#define NAND_BLOCK_SIZE SZ_128K
-#define GPMC_CS0_BASE 0x60
-#define GPMC_CS_SIZE 0x30
#define OVERO_SMSC911X_CS 5
#define OVERO_SMSC911X_GPIO 176
@@ -239,8 +237,6 @@ static void __init overo_flash_init(void)
u8 cs = 0;
u8 nandcs = GPMC_CS_NUM + 1;
- u32 gpmc_base_add = OMAP34XX_GPMC_VIRT;
-
/* find out the chip-select on which NAND exists */
while (cs < GPMC_CS_NUM) {
u32 ret = 0;
@@ -262,9 +258,6 @@ static void __init overo_flash_init(void)
if (nandcs < GPMC_CS_NUM) {
overo_nand_data.cs = nandcs;
- overo_nand_data.gpmc_cs_baseaddr = (void *)
- (gpmc_base_add + GPMC_CS0_BASE + nandcs * GPMC_CS_SIZE);
- overo_nand_data.gpmc_baseaddr = (void *) (gpmc_base_add);
printk(KERN_INFO "Registering NAND on CS%d\n", nandcs);
if (platform_device_register(&overo_nand_device) < 0)
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index 9c77af0..9210e10
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -64,16 +64,32 @@ static void __iomem *gpmc_base;
static struct clk *gpmc_l3_clk;
-static void gpmc_write_reg(int idx, u32 val)
+void gpmc_write_reg(int idx, u32 val)
{
__raw_writel(val, gpmc_base + idx);
}
-static u32 gpmc_read_reg(int idx)
+u32 gpmc_read_reg(int idx)
{
return __raw_readl(gpmc_base + idx);
}
+void gpmc_cs_write_byte(int cs, int idx, u32 val)
+{
+ void __iomem *reg_addr;
+
+ reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx;
+ __raw_writeb(val, reg_addr);
+}
+
+u8 gpmc_cs_read_byte(int cs, int idx)
+{
+ void __iomem *reg_addr;
+
+ reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx;
+ return __raw_readb(reg_addr);
+}
+
void gpmc_cs_write_reg(int cs, int idx, u32 val)
{
void __iomem *reg_addr;
@@ -432,15 +448,6 @@ void gpmc_prefetch_reset(void)
}
EXPORT_SYMBOL(gpmc_prefetch_reset);
-/**
- * gpmc_prefetch_status - reads prefetch status of engine
- */
-int gpmc_prefetch_status(void)
-{
- return gpmc_read_reg(GPMC_PREFETCH_STATUS);
-}
-EXPORT_SYMBOL(gpmc_prefetch_status);
-
static void __init gpmc_mem_init(void)
{
int cs;
diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h
index 347d212..c1e9807
--- a/arch/arm/plat-omap/include/plat/gpmc.h
+++ b/arch/arm/plat-omap/include/plat/gpmc.h
@@ -128,8 +128,12 @@ extern unsigned int gpmc_ticks_to_ns(unsigned int ticks);
extern unsigned int gpmc_round_ns_to_ticks(unsigned int time_ns);
extern unsigned long gpmc_get_fclk_period(void);
+extern void gpmc_write_reg(int idx, u32 val);
+extern u32 gpmc_read_reg(int idx);
extern void gpmc_cs_write_reg(int cs, int idx, u32 val);
extern u32 gpmc_cs_read_reg(int cs, int idx);
+extern void gpmc_cs_write_byte(int cs, int idx, u32 val);
+extern u8 gpmc_cs_read_byte(int cs, int idx);
extern int gpmc_cs_calc_divider(int cs, unsigned int sync_clk);
extern int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t);
extern int gpmc_cs_request(int cs, unsigned long size, unsigned long *base);
@@ -139,7 +143,6 @@ extern int gpmc_cs_reserved(int cs);
extern int gpmc_prefetch_enable(int cs, int dma_mode,
unsigned int u32_count, int is_write);
extern void gpmc_prefetch_reset(void);
-extern int gpmc_prefetch_status(void);
extern void omap3_gpmc_save_context(void);
extern void omap3_gpmc_restore_context(void);
extern void gpmc_init(void);
diff --git a/arch/arm/plat-omap/include/plat/nand.h b/arch/arm/plat-omap/include/plat/nand.h
index f8efd54..6562cd0
--- a/arch/arm/plat-omap/include/plat/nand.h
+++ b/arch/arm/plat-omap/include/plat/nand.h
@@ -21,13 +21,11 @@ struct omap_nand_platform_data {
int (*dev_ready)(struct omap_nand_platform_data *);
int dma_channel;
unsigned long phys_base;
- void __iomem *gpmc_cs_baseaddr;
- void __iomem *gpmc_baseaddr;
int devsize;
};
-/* size (4 KiB) for IO mapping */
-#define NAND_IO_SIZE SZ_4K
+/* minimum size for IO mapping */
+#define NAND_IO_SIZE 4
#if defined(CONFIG_MTD_NAND_OMAP2) || defined(CONFIG_MTD_NAND_OMAP2_MODULE)
extern int gpmc_nand_init(struct omap_nand_platform_data *d);
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 258bf06..f4f6f01
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -135,9 +135,6 @@ struct omap_nand_info {
int gpmc_cs;
unsigned long phys_base;
- void __iomem *gpmc_cs_baseaddr;
- void __iomem *gpmc_baseaddr;
- void __iomem *nand_pref_fifo_add;
struct completion comp;
int dma_ch;
};
@@ -149,17 +146,14 @@ struct omap_nand_info {
*/
static void omap_nand_wp(struct mtd_info *mtd, int mode)
{
- struct omap_nand_info *info = container_of(mtd,
- struct omap_nand_info, mtd);
-
- unsigned long config = __raw_readl(info->gpmc_baseaddr + GPMC_CONFIG);
+ unsigned long config = gpmc_read_reg(GPMC_CONFIG);
if (mode)
config &= ~(NAND_WP_BIT); /* WP is ON */
else
config |= (NAND_WP_BIT); /* WP is OFF */
- __raw_writel(config, (info->gpmc_baseaddr + GPMC_CONFIG));
+ gpmc_write_reg(GPMC_CONFIG, config);
}
/**
@@ -177,31 +171,20 @@ static void omap_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
struct omap_nand_info *info = container_of(mtd,
struct omap_nand_info, mtd);
- switch (ctrl) {
- case NAND_CTRL_CHANGE | NAND_CTRL_CLE:
- info->nand.IO_ADDR_W = info->gpmc_cs_baseaddr +
- GPMC_CS_NAND_COMMAND;
- info->nand.IO_ADDR_R = info->gpmc_cs_baseaddr +
- GPMC_CS_NAND_DATA;
- break;
- case NAND_CTRL_CHANGE | NAND_CTRL_ALE:
- info->nand.IO_ADDR_W = info->gpmc_cs_baseaddr +
- GPMC_CS_NAND_ADDRESS;
- info->nand.IO_ADDR_R = info->gpmc_cs_baseaddr +
- GPMC_CS_NAND_DATA;
- break;
+ if (cmd != NAND_CMD_NONE) {
+ if (ctrl & NAND_CLE) {
+ gpmc_cs_write_byte(info->gpmc_cs,
+ GPMC_CS_NAND_COMMAND, cmd);
- case NAND_CTRL_CHANGE | NAND_NCE:
- info->nand.IO_ADDR_W = info->gpmc_cs_baseaddr +
- GPMC_CS_NAND_DATA;
- info->nand.IO_ADDR_R = info->gpmc_cs_baseaddr +
- GPMC_CS_NAND_DATA;
- break;
- }
+ } else if (ctrl & NAND_ALE) {
+ gpmc_cs_write_byte(info->gpmc_cs,
+ GPMC_CS_NAND_ADDRESS, cmd);
- if (cmd != NAND_CMD_NONE)
- __raw_writeb(cmd, info->nand.IO_ADDR_W);
+ } else /* NAND_NCE */
+ gpmc_cs_write_byte(info->gpmc_cs,
+ GPMC_CS_NAND_DATA, cmd);
+ }
}
/**
@@ -231,8 +214,9 @@ static void omap_write_buf8(struct mtd_info *mtd, const u_char *buf, int len)
while (len--) {
iowrite8(*p++, info->nand.IO_ADDR_W);
- while (GPMC_BUF_EMPTY == (readl(info->gpmc_baseaddr +
- GPMC_STATUS) & GPMC_BUF_FULL));
+ while (GPMC_BUF_EMPTY ==
+ (gpmc_read_reg(GPMC_STATUS) & GPMC_BUF_FULL))
+ ;
}
}
@@ -267,8 +251,8 @@ static void omap_write_buf16(struct mtd_info *mtd, const u_char * buf, int len)
while (len--) {
iowrite16(*p++, info->nand.IO_ADDR_W);
- while (GPMC_BUF_EMPTY == (readl(info->gpmc_baseaddr +
- GPMC_STATUS) & GPMC_BUF_FULL))
+ while (GPMC_BUF_EMPTY ==
+ (gpmc_read_reg(GPMC_STATUS) & GPMC_BUF_FULL))
;
}
}
@@ -304,9 +288,9 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len)
omap_read_buf8(mtd, buf, len);
} else {
do {
- pfpw_status = gpmc_prefetch_status();
+ pfpw_status = gpmc_read_reg(GPMC_PREFETCH_STATUS);
r_count = ((pfpw_status >> 24) & 0x7F) >> 2;
- ioread32_rep(info->nand_pref_fifo_add, p, r_count);
+ ioread32_rep(info->nand.IO_ADDR_R, p, r_count);
p += r_count;
len -= r_count << 2;
} while (len);
@@ -347,12 +331,12 @@ static void omap_write_buf_pref(struct mtd_info *mtd,
else
omap_write_buf8(mtd, buf, len);
} else {
- pfpw_status = gpmc_prefetch_status();
+ pfpw_status = gpmc_read_reg(GPMC_PREFETCH_STATUS);
while (pfpw_status & 0x3FFF) {
w_count = ((pfpw_status >> 24) & 0x7F) >> 1;
for (i = 0; (i < w_count) && len; i++, len -= 2)
- iowrite16(*p++, info->nand_pref_fifo_add);
- pfpw_status = gpmc_prefetch_status();
+ iowrite16(*p++, info->nand.IO_ADDR_W);
+ pfpw_status = gpmc_read_reg(GPMC_PREFETCH_STATUS);
}
/* disable and stop the PFPW engine */
@@ -444,7 +428,7 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr,
/* setup and start DMA using dma_addr */
wait_for_completion(&info->comp);
- while (0x3fff & (prefetch_status = gpmc_prefetch_status()))
+ while (0x3fff & (prefetch_status = gpmc_read_reg(GPMC_PREFETCH_STATUS)))
;
/* disable and stop the PFPW engine */
gpmc_prefetch_reset();
@@ -498,7 +482,7 @@ static void omap_write_buf_dma_pref(struct mtd_info *mtd,
omap_write_buf_pref(mtd, buf, len);
else
/* start transfer in DMA mode */
- omap_nand_dma_transfer(mtd, buf, len, 0x1);
+ omap_nand_dma_transfer(mtd, (u_char *) buf, len, 0x1);
}
/**
@@ -529,22 +513,21 @@ static int omap_verify_buf(struct mtd_info *mtd, const u_char * buf, int len)
*/
static void omap_hwecc_init(struct mtd_info *mtd)
{
- struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
- mtd);
struct nand_chip *chip = mtd->priv;
unsigned long val = 0x0;
/* Read from ECC Control Register */
- val = __raw_readl(info->gpmc_baseaddr + GPMC_ECC_CONTROL);
+ val = gpmc_read_reg(GPMC_ECC_CONTROL);
+
/* Clear all ECC | Enable Reg1 */
val = ((0x00000001<<8) | 0x00000001);
- __raw_writel(val, info->gpmc_baseaddr + GPMC_ECC_CONTROL);
+ gpmc_write_reg(GPMC_ECC_CONTROL, val);
/* Read from ECC Size Config Register */
- val = __raw_readl(info->gpmc_baseaddr + GPMC_ECC_SIZE_CONFIG);
+ val = gpmc_read_reg(GPMC_ECC_SIZE_CONFIG);
/* ECCSIZE1=512 | Select eccResultsize[0-3] */
val = ((((chip->ecc.size >> 1) - 1) << 22) | (0x0000000F));
- __raw_writel(val, info->gpmc_baseaddr + GPMC_ECC_SIZE_CONFIG);
+ gpmc_write_reg(GPMC_ECC_SIZE_CONFIG, val);
}
/**
@@ -746,19 +729,14 @@ static int omap_correct_data(struct mtd_info *mtd, u_char *dat,
static int omap_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
u_char *ecc_code)
{
- struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
- mtd);
unsigned long val = 0x0;
- unsigned long reg;
/* Start Reading from HW ECC1_Result = 0x200 */
- reg = (unsigned long)(info->gpmc_baseaddr + GPMC_ECC1_RESULT);
- val = __raw_readl(reg);
+ val = gpmc_read_reg(GPMC_ECC1_RESULT);
*ecc_code++ = val; /* P128e, ..., P1e */
*ecc_code++ = val >> 16; /* P128o, ..., P1o */
/* P2048o, P1024o, P512o, P256o, P2048e, P1024e, P512e, P256e */
*ecc_code++ = ((val >> 8) & 0x0f) | ((val >> 20) & 0xf0);
- reg += 4;
return 0;
}
@@ -774,21 +752,21 @@ static void omap_enable_hwecc(struct mtd_info *mtd, int mode)
mtd);
struct nand_chip *chip = mtd->priv;
unsigned int dev_width = (chip->options & NAND_BUSWIDTH_16) ? 1 : 0;
- unsigned long val = __raw_readl(info->gpmc_baseaddr + GPMC_ECC_CONFIG);
+ unsigned long val = gpmc_read_reg(GPMC_ECC_CONFIG);
switch (mode) {
case NAND_ECC_READ:
- __raw_writel(0x101, info->gpmc_baseaddr + GPMC_ECC_CONTROL);
+ gpmc_write_reg(GPMC_ECC_CONTROL, 0x101);
/* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */
val = (dev_width << 7) | (info->gpmc_cs << 1) | (0x1);
break;
case NAND_ECC_READSYN:
- __raw_writel(0x100, info->gpmc_baseaddr + GPMC_ECC_CONTROL);
+ gpmc_write_reg(GPMC_ECC_CONTROL, 0x100);
/* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */
val = (dev_width << 7) | (info->gpmc_cs << 1) | (0x1);
break;
case NAND_ECC_WRITE:
- __raw_writel(0x101, info->gpmc_baseaddr + GPMC_ECC_CONTROL);
+ gpmc_write_reg(GPMC_ECC_CONTROL, 0x101);
/* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */
val = (dev_width << 7) | (info->gpmc_cs << 1) | (0x1);
break;
@@ -798,7 +776,7 @@ static void omap_enable_hwecc(struct mtd_info *mtd, int mode)
break;
}
- __raw_writel(val, info->gpmc_baseaddr + GPMC_ECC_CONFIG);
+ gpmc_write_reg(GPMC_ECC_CONFIG, val);
}
#endif
@@ -827,14 +805,11 @@ static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip)
else
timeo += (HZ * 20) / 1000;
- this->IO_ADDR_W = (void *) info->gpmc_cs_baseaddr +
- GPMC_CS_NAND_COMMAND;
- this->IO_ADDR_R = (void *) info->gpmc_cs_baseaddr + GPMC_CS_NAND_DATA;
-
- __raw_writeb(NAND_CMD_STATUS & 0xFF, this->IO_ADDR_W);
+ gpmc_cs_write_byte(info->gpmc_cs,
+ GPMC_CS_NAND_COMMAND, (NAND_CMD_STATUS & 0xFF));
while (time_before(jiffies, timeo)) {
- status = __raw_readb(this->IO_ADDR_R);
+ status = gpmc_cs_read_byte(info->gpmc_cs, GPMC_CS_NAND_DATA);
if (status & NAND_STATUS_READY)
break;
cond_resched();
@@ -848,22 +823,19 @@ static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip)
*/
static int omap_dev_ready(struct mtd_info *mtd)
{
- struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
- mtd);
- unsigned int val = __raw_readl(info->gpmc_baseaddr + GPMC_IRQSTATUS);
+ unsigned int val = gpmc_read_reg(GPMC_IRQSTATUS);
if ((val & 0x100) == 0x100) {
/* Clear IRQ Interrupt */
val |= 0x100;
val &= ~(0x0);
- __raw_writel(val, info->gpmc_baseaddr + GPMC_IRQSTATUS);
+ gpmc_write_reg(GPMC_IRQSTATUS, val);
} else {
unsigned int cnt = 0;
while (cnt++ < 0x1FF) {
if ((val & 0x100) == 0x100)
return 0;
- val = __raw_readl(info->gpmc_baseaddr +
- GPMC_IRQSTATUS);
+ val = gpmc_read_reg(GPMC_IRQSTATUS);
}
}
@@ -894,8 +866,6 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
info->pdev = pdev;
info->gpmc_cs = pdata->cs;
- info->gpmc_baseaddr = pdata->gpmc_baseaddr;
- info->gpmc_cs_baseaddr = pdata->gpmc_cs_baseaddr;
info->phys_base = pdata->phys_base;
info->mtd.priv = &info->nand;
@@ -942,7 +912,6 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
if (use_prefetch) {
/* copy the virtual address of nand base for fifo access */
- info->nand_pref_fifo_add = info->nand.IO_ADDR_R;
info->nand.read_buf = omap_read_buf_pref;
info->nand.write_buf = omap_write_buf_pref;
@@ -1032,7 +1001,7 @@ static int omap_nand_remove(struct platform_device *pdev)
/* Release NAND device, its internal structures and partitions */
nand_release(&info->mtd);
- iounmap(info->nand_pref_fifo_add);
+ iounmap(info->nand.IO_ADDR_R);
kfree(&info->mtd);
return 0;
}
^ permalink raw reply related [flat|nested] 102+ messages in thread
* [PATCH 3/3] omap3 nand: fix issue in board file to detect the nand
2010-05-12 9:48 ` [PATCH 2/3] omap3 nand: cleanup for not to use GPMC virtual address Sukumar Ghorai
@ 2010-05-12 9:48 ` Sukumar Ghorai
2010-05-13 15:41 ` [PATCH 2/3] omap3 nand: cleanup for not to use GPMC virtual address Tony Lindgren
1 sibling, 0 replies; 102+ messages in thread
From: Sukumar Ghorai @ 2010-05-12 9:48 UTC (permalink / raw)
To: linux-omap
Cc: linux-mtd, tony, sakoman, mike, Artem.Bityutskiy, Sukumar Ghorai
Board file modified to pass the GMPC phys_base address to nand driver. This is
required to adopt the _prob function as in omap2.c
Signed-off-by: Sukumar Ghorai <s-ghorai@ti.com>
---
arch/arm/mach-omap2/board-cm-t35.c | 16 +---------------
arch/arm/mach-omap2/board-devkit8000.c | 16 +---------------
arch/arm/mach-omap2/board-omap3beagle.c | 16 +---------------
arch/arm/mach-omap2/board-omap3touchbook.c | 16 +---------------
arch/arm/mach-omap2/board-overo.c | 17 +----------------
5 files changed, 5 insertions(+), 76 deletions(-)
diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c
index fb23122..0544294
--- a/arch/arm/mach-omap2/board-cm-t35.c
+++ b/arch/arm/mach-omap2/board-cm-t35.c
@@ -224,23 +224,9 @@ static struct omap_nand_platform_data cm_t35_nand_data = {
};
-static struct resource cm_t35_nand_resource = {
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device cm_t35_nand_device = {
- .name = "omap2-nand",
- .id = -1,
- .num_resources = 1,
- .resource = &cm_t35_nand_resource,
- .dev = {
- .platform_data = &cm_t35_nand_data,
- },
-};
-
static void __init cm_t35_init_nand(void)
{
- if (platform_device_register(&cm_t35_nand_device) < 0)
+ if (gpmc_nand_init(&cm_t35_nand_data) < 0)
pr_err("CM-T35: Unable to register NAND device\n");
}
#else
diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c
index be50d18..a6fcb48
--- a/arch/arm/mach-omap2/board-devkit8000.c
+++ b/arch/arm/mach-omap2/board-devkit8000.c
@@ -101,20 +101,6 @@ static struct omap_nand_platform_data devkit8000_nand_data = {
.dma_channel = -1, /* disable DMA in OMAP NAND driver */
};
-static struct resource devkit8000_nand_resource = {
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device devkit8000_nand_device = {
- .name = "omap2-nand",
- .id = -1,
- .dev = {
- .platform_data = &devkit8000_nand_data,
- },
- .num_resources = 1,
- .resource = &devkit8000_nand_resource,
-};
-
static struct omap2_hsmmc_info mmc[] = {
{
.mmc = 1,
@@ -601,7 +587,7 @@ static void __init devkit8000_flash_init(void)
devkit8000_nand_data.cs = nandcs;
printk(KERN_INFO "Registering NAND on CS%d\n", nandcs);
- if (platform_device_register(&devkit8000_nand_device) < 0)
+ if (gpmc_nand_init(&devkit8000_nand_data) < 0)
printk(KERN_ERR "Unable to register NAND device\n");
}
}
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index becaebe..bf31b7c
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -89,20 +89,6 @@ static struct omap_nand_platform_data omap3beagle_nand_data = {
.dev_ready = NULL,
};
-static struct resource omap3beagle_nand_resource = {
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device omap3beagle_nand_device = {
- .name = "omap2-nand",
- .id = -1,
- .dev = {
- .platform_data = &omap3beagle_nand_data,
- },
- .num_resources = 1,
- .resource = &omap3beagle_nand_resource,
-};
-
#include "sdram-micron-mt46h32m32lf-6.h"
static struct omap2_hsmmc_info mmc[] = {
@@ -397,7 +383,7 @@ static void __init omap3beagle_flash_init(void)
omap3beagle_nand_data.cs = nandcs;
printk(KERN_INFO "Registering NAND on CS%d\n", nandcs);
- if (platform_device_register(&omap3beagle_nand_device) < 0)
+ if (gpmc_nand_init(&omap3beagle_nand_data) < 0)
printk(KERN_ERR "Unable to register NAND device\n");
}
}
diff --git a/arch/arm/mach-omap2/board-omap3touchbook.c b/arch/arm/mach-omap2/board-omap3touchbook.c
index d6f1b12..e8ad30c
--- a/arch/arm/mach-omap2/board-omap3touchbook.c
+++ b/arch/arm/mach-omap2/board-omap3touchbook.c
@@ -103,20 +103,6 @@ static struct omap_nand_platform_data omap3touchbook_nand_data = {
.dev_ready = NULL,
};
-static struct resource omap3touchbook_nand_resource = {
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device omap3touchbook_nand_device = {
- .name = "omap2-nand",
- .id = -1,
- .dev = {
- .platform_data = &omap3touchbook_nand_data,
- },
- .num_resources = 1,
- .resource = &omap3touchbook_nand_resource,
-};
-
#include "sdram-micron-mt46h32m32lf-6.h"
static struct omap2_hsmmc_info mmc[] = {
@@ -479,7 +465,7 @@ static void __init omap3touchbook_flash_init(void)
omap3touchbook_nand_data.cs = nandcs;
printk(KERN_INFO "Registering NAND on CS%d\n", nandcs);
- if (platform_device_register(&omap3touchbook_nand_device) < 0)
+ if (gpmc_nand_init(&omap3touchbook_nand_data) < 0)
printk(KERN_ERR "Unable to register NAND device\n");
}
}
diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
index d843a0a..627edd3
--- a/arch/arm/mach-omap2/board-overo.c
+++ b/arch/arm/mach-omap2/board-overo.c
@@ -217,21 +217,6 @@ static struct omap_nand_platform_data overo_nand_data = {
.dma_channel = -1, /* disable DMA in OMAP NAND driver */
};
-static struct resource overo_nand_resource = {
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device overo_nand_device = {
- .name = "omap2-nand",
- .id = -1,
- .dev = {
- .platform_data = &overo_nand_data,
- },
- .num_resources = 1,
- .resource = &overo_nand_resource,
-};
-
-
static void __init overo_flash_init(void)
{
u8 cs = 0;
@@ -260,7 +245,7 @@ static void __init overo_flash_init(void)
overo_nand_data.cs = nandcs;
printk(KERN_INFO "Registering NAND on CS%d\n", nandcs);
- if (platform_device_register(&overo_nand_device) < 0)
+ if (gpmc_nand_init(&overo_nand_data) < 0)
printk(KERN_ERR "Unable to register NAND device\n");
}
}
^ permalink raw reply related [flat|nested] 102+ messages in thread
* Re: [PATCH 1/3] omap3: GPMC register definition at common location
2010-05-12 9:48 ` [PATCH 1/3] omap3: GPMC register definition at common location Sukumar Ghorai
2010-05-12 9:48 ` [PATCH 2/3] omap3 nand: cleanup for not to use GPMC virtual address Sukumar Ghorai
@ 2010-05-13 6:15 ` Mike Rapoport
2010-05-13 15:41 ` Tony Lindgren
2 siblings, 0 replies; 102+ messages in thread
From: Mike Rapoport @ 2010-05-13 6:15 UTC (permalink / raw)
To: Sukumar Ghorai
Cc: linux-omap, linux-mtd, tony, sakoman, Artem.Bityutskiy,
Mike Rapoport
Sukumar Ghorai wrote:
> GPMC register definition move to common place in gpmc.h.
>
> Signed-off-by: Sukumar Ghorai <s-ghorai@ti.com>
Looks Ok to me, just minor comments
> ---
> arch/arm/mach-omap2/gpmc.c | 38 +------------------------------
> arch/arm/plat-omap/include/plat/gpmc.h | 36 +++++++++++++++++++++++++++--
> drivers/mtd/nand/omap2.c | 14 ++++-------
> 3 files changed, 40 insertions(+), 48 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
> index 5bc3ca0..9c77af0
> --- a/arch/arm/mach-omap2/gpmc.c
> +++ b/arch/arm/mach-omap2/gpmc.c
> @@ -28,40 +28,6 @@
>
> #include <plat/sdrc.h>
>
> -/* GPMC register offsets */
> -#define GPMC_REVISION 0x00
> -#define GPMC_SYSCONFIG 0x10
> -#define GPMC_SYSSTATUS 0x14
> -#define GPMC_IRQSTATUS 0x18
> -#define GPMC_IRQENABLE 0x1c
> -#define GPMC_TIMEOUT_CONTROL 0x40
> -#define GPMC_ERR_ADDRESS 0x44
> -#define GPMC_ERR_TYPE 0x48
> -#define GPMC_CONFIG 0x50
> -#define GPMC_STATUS 0x54
> -#define GPMC_PREFETCH_CONFIG1 0x1e0
> -#define GPMC_PREFETCH_CONFIG2 0x1e4
> -#define GPMC_PREFETCH_CONTROL 0x1ec
> -#define GPMC_PREFETCH_STATUS 0x1f0
> -#define GPMC_ECC_CONFIG 0x1f4
> -#define GPMC_ECC_CONTROL 0x1f8
> -#define GPMC_ECC_SIZE_CONFIG 0x1fc
> -
> -#define GPMC_CS0 0x60
> -#define GPMC_CS_SIZE 0x30
> -
> -#define GPMC_MEM_START 0x00000000
> -#define GPMC_MEM_END 0x3FFFFFFF
> -#define BOOT_ROM_SPACE 0x100000 /* 1MB */
> -
> -#define GPMC_CHUNK_SHIFT 24 /* 16 MB */
> -#define GPMC_SECTION_SHIFT 28 /* 128 MB */
> -
> -#define PREFETCH_FIFOTHRESHOLD (0x40 << 8)
> -#define CS_NUM_SHIFT 24
> -#define ENABLE_PREFETCH (0x1 << 7)
> -#define DMA_MPU_MODE 2
> -
> /* Structure to save gpmc cs context */
> struct gpmc_cs_config {
> u32 config1;
> @@ -112,7 +78,7 @@ void gpmc_cs_write_reg(int cs, int idx, u32 val)
> {
> void __iomem *reg_addr;
>
> - reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx;
> + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx;
> __raw_writel(val, reg_addr);
> }
>
> @@ -120,7 +86,7 @@ u32 gpmc_cs_read_reg(int cs, int idx)
> {
> void __iomem *reg_addr;
>
> - reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx;
> + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx;
> return __raw_readl(reg_addr);
> }
>
> diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h
> index 145838a..347d212 100644
> --- a/arch/arm/plat-omap/include/plat/gpmc.h
> +++ b/arch/arm/plat-omap/include/plat/gpmc.h
> @@ -25,10 +25,40 @@
> #define GPMC_CS_NAND_ADDRESS 0x20
> #define GPMC_CS_NAND_DATA 0x24
>
> -#define GPMC_CONFIG 0x50
> -#define GPMC_STATUS 0x54
> +/* GPMC register offsets */
> +#define GPMC_REVISION 0x00
> +#define GPMC_SYSCONFIG 0x10
> +#define GPMC_SYSSTATUS 0x14
> +#define GPMC_IRQSTATUS 0x18
> +#define GPMC_IRQENABLE 0x1c
> +#define GPMC_TIMEOUT_CONTROL 0x40
> +#define GPMC_ERR_ADDRESS 0x44
> +#define GPMC_ERR_TYPE 0x48
> +#define GPMC_CONFIG 0x50
> +#define GPMC_STATUS 0x54
> +#define GPMC_PREFETCH_CONFIG1 0x1e0
> +#define GPMC_PREFETCH_CONFIG2 0x1e4
> +#define GPMC_PREFETCH_CONTROL 0x1ec
> +#define GPMC_PREFETCH_STATUS 0x1f0
> +#define GPMC_ECC_CONFIG 0x1f4
> +#define GPMC_ECC_CONTROL 0x1f8
> +#define GPMC_ECC_SIZE_CONFIG 0x1fc
> +#define GPMC_ECC1_RESULT 0x200
> +
> #define GPMC_CS0_BASE 0x60
> -#define GPMC_CS_SIZE 0x30
> +#define GPMC_CS_SIZE 0x30
> +
> +#define GPMC_MEM_START 0x00000000
> +#define GPMC_MEM_END 0x3FFFFFFF
> +#define BOOT_ROM_SPACE 0x100000 /* 1MB */
> +
> +#define GPMC_CHUNK_SHIFT 24 /* 16 MB */
> +#define GPMC_SECTION_SHIFT 28 /* 128 MB */
> +
> +#define PREFETCH_FIFOTHRESHOLD (0x40 << 8)
> +#define CS_NUM_SHIFT 24
> +#define ENABLE_PREFETCH (0x1 << 7)
> +#define DMA_MPU_MODE 2
>
> #define GPMC_CONFIG1_WRAPBURST_SUPP (1 << 31)
> #define GPMC_CONFIG1_READMULTIPLE_SUPP (1 << 30)
> diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
> index 7545568..258bf06
> --- a/drivers/mtd/nand/omap2.c
> +++ b/drivers/mtd/nand/omap2.c
> @@ -23,12 +23,6 @@
> #include <plat/gpmc.h>
> #include <plat/nand.h>
>
> -#define GPMC_IRQ_STATUS 0x18
> -#define GPMC_ECC_CONFIG 0x1F4
> -#define GPMC_ECC_CONTROL 0x1F8
> -#define GPMC_ECC_SIZE_CONFIG 0x1FC
> -#define GPMC_ECC1_RESULT 0x200
> -
> #define DRIVER_NAME "omap2-nand"
>
> #define NAND_WP_OFF 0
> @@ -37,6 +31,7 @@
> #define GPMC_BUF_FULL 0x00000001
> #define GPMC_BUF_EMPTY 0x00000000
>
> +#ifdef CONFIG_MTD_NAND_OMAP_HWECC
This change does not seem related to the patch subject.
> #define NAND_Ecc_P1e (1 << 0)
> #define NAND_Ecc_P2e (1 << 1)
> #define NAND_Ecc_P4e (1 << 2)
> @@ -103,6 +98,7 @@
>
> #define P4e_s(a) (TF(a & NAND_Ecc_P4e) << 0)
> #define P4o_s(a) (TF(a & NAND_Ecc_P4o) << 1)
> +#endif /* CONFIG_MTD_NAND_OMAP_HWECC */
>
> #ifdef CONFIG_MTD_PARTITIONS
> static const char *part_probes[] = { "cmdlinepart", NULL };
> @@ -854,20 +850,20 @@ static int omap_dev_ready(struct mtd_info *mtd)
> {
> struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
> mtd);
> - unsigned int val = __raw_readl(info->gpmc_baseaddr + GPMC_IRQ_STATUS);
> + unsigned int val = __raw_readl(info->gpmc_baseaddr + GPMC_IRQSTATUS);
>
> if ((val & 0x100) == 0x100) {
> /* Clear IRQ Interrupt */
> val |= 0x100;
> val &= ~(0x0);
> - __raw_writel(val, info->gpmc_baseaddr + GPMC_IRQ_STATUS);
> + __raw_writel(val, info->gpmc_baseaddr + GPMC_IRQSTATUS);
> } else {
> unsigned int cnt = 0;
> while (cnt++ < 0x1FF) {
> if ((val & 0x100) == 0x100)
> return 0;
> val = __raw_readl(info->gpmc_baseaddr +
> - GPMC_IRQ_STATUS);
> + GPMC_IRQSTATUS);
> }
> }
>
--
Sincerely yours,
Mike.
^ permalink raw reply [flat|nested] 102+ messages in thread
* Re: [PATCH 2/3] omap3 nand: cleanup for not to use GPMC virtual address
2010-05-12 9:48 ` [PATCH 2/3] omap3 nand: cleanup for not to use GPMC virtual address Sukumar Ghorai
2010-05-12 9:48 ` [PATCH 3/3] omap3 nand: fix issue in board file to detect the nand Sukumar Ghorai
@ 2010-05-13 15:41 ` Tony Lindgren
2010-05-13 18:48 ` Ghorai, Sukumar
1 sibling, 1 reply; 102+ messages in thread
From: Tony Lindgren @ 2010-05-13 15:41 UTC (permalink / raw)
To: Sukumar Ghorai; +Cc: linux-omap, linux-mtd, sakoman, mike, Artem.Bityutskiy
* Sukumar Ghorai <s-ghorai@ti.com> [100512 02:43]:
> --- a/arch/arm/mach-omap2/gpmc.c
> +++ b/arch/arm/mach-omap2/gpmc.c
> @@ -64,16 +64,32 @@ static void __iomem *gpmc_base;
>
> static struct clk *gpmc_l3_clk;
>
> -static void gpmc_write_reg(int idx, u32 val)
> +void gpmc_write_reg(int idx, u32 val)
> {
> __raw_writel(val, gpmc_base + idx);
> }
>
> -static u32 gpmc_read_reg(int idx)
> +u32 gpmc_read_reg(int idx)
> {
> return __raw_readl(gpmc_base + idx);
> }
>
> +void gpmc_cs_write_byte(int cs, int idx, u32 val)
> +{
> + void __iomem *reg_addr;
> +
> + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx;
> + __raw_writeb(val, reg_addr);
> +}
> +
> +u8 gpmc_cs_read_byte(int cs, int idx)
> +{
> + void __iomem *reg_addr;
> +
> + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx;
> + return __raw_readb(reg_addr);
> +}
> +
This will not improve the situation unfortunately.
We for sure don't want to export functions to mess
with the GPMC registers all over the place.
> @@ -432,15 +448,6 @@ void gpmc_prefetch_reset(void)
> }
> EXPORT_SYMBOL(gpmc_prefetch_reset);
>
> -/**
> - * gpmc_prefetch_status - reads prefetch status of engine
> - */
> -int gpmc_prefetch_status(void)
> -{
> - return gpmc_read_reg(GPMC_PREFETCH_STATUS);
> -}
> -EXPORT_SYMBOL(gpmc_prefetch_status);
> -
And we don't want to remove GPMC functions like this,
instead we need to implement more functions like this
for the platform init code to use.
Regards,
Tony
^ permalink raw reply [flat|nested] 102+ messages in thread
* Re: [PATCH 1/3] omap3: GPMC register definition at common location
2010-05-12 9:48 ` [PATCH 1/3] omap3: GPMC register definition at common location Sukumar Ghorai
2010-05-12 9:48 ` [PATCH 2/3] omap3 nand: cleanup for not to use GPMC virtual address Sukumar Ghorai
2010-05-13 6:15 ` [PATCH 1/3] omap3: GPMC register definition at common location Mike Rapoport
@ 2010-05-13 15:41 ` Tony Lindgren
2 siblings, 0 replies; 102+ messages in thread
From: Tony Lindgren @ 2010-05-13 15:41 UTC (permalink / raw)
To: Sukumar Ghorai; +Cc: linux-omap, linux-mtd, sakoman, mike, Artem.Bityutskiy
* Sukumar Ghorai <s-ghorai@ti.com> [100512 02:43]:
> --- a/arch/arm/plat-omap/include/plat/gpmc.h
> +++ b/arch/arm/plat-omap/include/plat/gpmc.h
> @@ -25,10 +25,40 @@
> #define GPMC_CS_NAND_ADDRESS 0x20
> #define GPMC_CS_NAND_DATA 0x24
>
> -#define GPMC_CONFIG 0x50
> -#define GPMC_STATUS 0x54
> +/* GPMC register offsets */
> +#define GPMC_REVISION 0x00
> +#define GPMC_SYSCONFIG 0x10
> +#define GPMC_SYSSTATUS 0x14
> +#define GPMC_IRQSTATUS 0x18
> +#define GPMC_IRQENABLE 0x1c
> +#define GPMC_TIMEOUT_CONTROL 0x40
> +#define GPMC_ERR_ADDRESS 0x44
> +#define GPMC_ERR_TYPE 0x48
> +#define GPMC_CONFIG 0x50
> +#define GPMC_STATUS 0x54
> +#define GPMC_PREFETCH_CONFIG1 0x1e0
> +#define GPMC_PREFETCH_CONFIG2 0x1e4
> +#define GPMC_PREFETCH_CONTROL 0x1ec
> +#define GPMC_PREFETCH_STATUS 0x1f0
> +#define GPMC_ECC_CONFIG 0x1f4
> +#define GPMC_ECC_CONTROL 0x1f8
> +#define GPMC_ECC_SIZE_CONFIG 0x1fc
> +#define GPMC_ECC1_RESULT 0x200
...
No thanks, that will just make the situation worse
leading into all the drivers messing with the GPMC
registers.
Tony
^ permalink raw reply [flat|nested] 102+ messages in thread
* Re: [PATCH 0/3] omap3 nand: cleanup exiting platform related code
2010-05-12 9:48 ` [PATCH 0/3] omap3 nand: cleanup exiting platform related code Sukumar Ghorai
2010-05-12 9:48 ` [PATCH 1/3] omap3: GPMC register definition at common location Sukumar Ghorai
@ 2010-05-13 15:44 ` Tony Lindgren
1 sibling, 0 replies; 102+ messages in thread
From: Tony Lindgren @ 2010-05-13 15:44 UTC (permalink / raw)
To: Sukumar Ghorai; +Cc: linux-omap, linux-mtd, sakoman, mike, Artem.Bityutskiy
* Sukumar Ghorai <s-ghorai@ti.com> [100512 02:43]:
> The following set of patches applies on top of master branch.
> http://git.kernel.org/?p=linux/kernel/git/tmlind/linux-omap-2.6.git
> Patches verified on: omap3430-SDP, omap3630-sdp, zoom3 and beagle board
>
> And these are the patches required to address the following input -
> 1. The NAND driver needs to stop tinkering with the GPMC registers
> The omap General Purpose Memory Controller (GPMC) registers are omap
> specific, and not driver specific. Tinkering with these registers can
> cause issues with the other devices on the GPMC.
>
> 2. Passing hardcoded GPMC_CS0_BASE needs to go from the board files
> Passing hardcoded GPMC virtual addressess is sure way to mess up things.
> This should all become unnecessary once the NAND drivers stops messing
> with the GPMC registers directly.
Thanks for working on this. I've made some comments to you patches
to do what's listed above.
Instead of exporting the GPMC registers, you should create new
functions into gpmc.c for the nand platform init code to use.
Regards,
Tony
^ permalink raw reply [flat|nested] 102+ messages in thread
* RE: [PATCH 2/3] omap3 nand: cleanup for not to use GPMC virtual address
2010-05-13 15:41 ` [PATCH 2/3] omap3 nand: cleanup for not to use GPMC virtual address Tony Lindgren
@ 2010-05-13 18:48 ` Ghorai, Sukumar
0 siblings, 0 replies; 102+ messages in thread
From: Ghorai, Sukumar @ 2010-05-13 18:48 UTC (permalink / raw)
To: Tony Lindgren
Cc: linux-omap@vger.kernel.org, linux-mtd@lists.infradead.org,
sakoman@gmail.com, mike@compulab.co.il,
Artem.Bityutskiy@nokia.com
Tony,
> -----Original Message-----
> From: Tony Lindgren [mailto:tony@atomide.com]
> Sent: 2010-05-13 21:11
> To: Ghorai, Sukumar
> Cc: linux-omap@vger.kernel.org; linux-mtd@lists.infradead.org;
> sakoman@gmail.com; mike@compulab.co.il; Artem.Bityutskiy@nokia.com
> Subject: Re: [PATCH 2/3] omap3 nand: cleanup for not to use GPMC virtual
> address
>
> * Sukumar Ghorai <s-ghorai@ti.com> [100512 02:43]:
> > --- a/arch/arm/mach-omap2/gpmc.c
> > +++ b/arch/arm/mach-omap2/gpmc.c
> > @@ -64,16 +64,32 @@ static void __iomem *gpmc_base;
> >
> > static struct clk *gpmc_l3_clk;
> >
> > -static void gpmc_write_reg(int idx, u32 val)
> > +void gpmc_write_reg(int idx, u32 val)
> > {
> > __raw_writel(val, gpmc_base + idx);
> > }
> >
> > -static u32 gpmc_read_reg(int idx)
> > +u32 gpmc_read_reg(int idx)
> > {
> > return __raw_readl(gpmc_base + idx);
> > }
> >
> > +void gpmc_cs_write_byte(int cs, int idx, u32 val)
> > +{
> > + void __iomem *reg_addr;
> > +
> > + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx;
> > + __raw_writeb(val, reg_addr);
> > +}
> > +
> > +u8 gpmc_cs_read_byte(int cs, int idx)
> > +{
> > + void __iomem *reg_addr;
> > +
> > + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx;
> > + return __raw_readb(reg_addr);
> > +}
> > +
>
> This will not improve the situation unfortunately.
> We for sure don't want to export functions to mess
> with the GPMC registers all over the place.
>
> > @@ -432,15 +448,6 @@ void gpmc_prefetch_reset(void)
> > }
> > EXPORT_SYMBOL(gpmc_prefetch_reset);
> >
> > -/**
> > - * gpmc_prefetch_status - reads prefetch status of engine
> > - */
> > -int gpmc_prefetch_status(void)
> > -{
> > - return gpmc_read_reg(GPMC_PREFETCH_STATUS);
> > -}
> > -EXPORT_SYMBOL(gpmc_prefetch_status);
> > -
>
> And we don't want to remove GPMC functions like this,
> instead we need to implement more functions like this
> for the platform init code to use.
[Ghorai]
1. NAND IO address needed by core NAND driver. So we can't move that access to GMPC.
2. And is it ok if we add functions as below and all need to be as EXPORT_SYMBOL too?
get_gpmc_status()
get_gpmc_irq_status()
set_gpmc_irq_status()
set_gpmc_irq_enable()
get_gpmc_config
set_gpmc_config
get_gpmc_status()
get_gpmc_prefetch_config()
gpmc_prefetch_status
set_gpmc_ecc_config
set_gpmc_ecc_contol
set_gpmc_ecc_size
get_gpmc_ecc_result
Regards,
Sukumar
> Regards,
>
> Tony
^ permalink raw reply [flat|nested] 102+ messages in thread
* [PATCH v2 0/2] omap3 nand: cleanup exiting platform related code
[not found] <Sukumar Ghorai <s-ghorai@ti.com>
` (10 preceding siblings ...)
2010-05-12 9:48 ` [PATCH 0/3] omap3 nand: cleanup exiting platform related code Sukumar Ghorai
@ 2010-05-14 15:23 ` Sukumar Ghorai
2010-05-14 15:23 ` [PATCH v2 1/2] omap3 nand: cleanup for not to use GPMC virtual address Sukumar Ghorai
2010-05-18 11:16 ` [PATCH v3 0/3] omap3 nand: cleanup exiting platform related code Sukumar Ghorai
` (3 subsequent siblings)
15 siblings, 1 reply; 102+ messages in thread
From: Sukumar Ghorai @ 2010-05-14 15:23 UTC (permalink / raw)
To: linux-omap
Cc: linux-mtd, tony, sakoman, mike, Artem.Bityutskiy, Sukumar Ghorai
v2:
The following set of patches applies on top of master branch.
http://git.kernel.org/?p=linux/kernel/git/tmlind/linux-omap-2.6.git
Patches verified on: omap3430-SDP, omap3630-sdp, zoom3 and beagle board
And these are the patches required to address the following input -
1. The NAND driver needs to stop tinkering with the GPMC registers
The omap General Purpose Memory Controller (GPMC) registers are omap
specific, and not driver specific. Tinkering with these registers can
cause issues with the other devices on the GPMC.
2. Passing hardcoded GPMC_CS0_BASE needs to go from the board files
Passing hardcoded GPMC virtual addressess is sure way to mess up things.
This should all become unnecessary once the NAND drivers stops messing
with the GPMC registers directly.
v1: http://www.mail-archive.com/linux-omap@vger.kernel.org/msg28164.html
Sukumar Ghorai (2):
omap3 nand: cleanup for not to use GPMC virtual address
omap3 nand: fix issue in board file to detect the nand
arch/arm/mach-omap2/board-cm-t35.c | 20 +---
arch/arm/mach-omap2/board-devkit8000.c | 25 +---
arch/arm/mach-omap2/board-omap3beagle.c | 24 +---
arch/arm/mach-omap2/board-omap3touchbook.c | 25 +---
arch/arm/mach-omap2/board-overo.c | 24 +---
arch/arm/mach-omap2/gpmc-nand.c | 38 ++----
arch/arm/mach-omap2/gpmc-onenand.c | 2 +-
arch/arm/mach-omap2/gpmc.c | 244 ++++++++++++++++++++++++----
arch/arm/plat-omap/include/plat/gpmc.h | 36 ++++-
arch/arm/plat-omap/include/plat/nand.h | 6 +-
drivers/mtd/nand/omap2.c | 190 ++++++----------------
11 files changed, 306 insertions(+), 328 deletions(-)
^ permalink raw reply [flat|nested] 102+ messages in thread
* [PATCH v2 1/2] omap3 nand: cleanup for not to use GPMC virtual address
2010-05-14 15:23 ` [PATCH v2 0/2] " Sukumar Ghorai
@ 2010-05-14 15:23 ` Sukumar Ghorai
2010-05-14 15:23 ` [PATCH v2 2/2] omap3 nand: fix issue in board file to detect the nand Sukumar Ghorai
` (3 more replies)
0 siblings, 4 replies; 102+ messages in thread
From: Sukumar Ghorai @ 2010-05-14 15:23 UTC (permalink / raw)
To: linux-omap
Cc: linux-mtd, tony, sakoman, mike, Artem.Bityutskiy, Sukumar Ghorai
Necessary function added in GPMC module and used by nand driver. This is for
not to use GPMC address directly from nand driver. Also it was passing GPMC
base address from board files and that is removed.
Signed-off-by: Sukumar Ghorai <s-ghorai@ti.com>
---
arch/arm/mach-omap2/board-cm-t35.c | 4 -
arch/arm/mach-omap2/board-devkit8000.c | 9 -
arch/arm/mach-omap2/board-omap3beagle.c | 8 -
arch/arm/mach-omap2/board-omap3touchbook.c | 9 -
arch/arm/mach-omap2/board-overo.c | 7 -
arch/arm/mach-omap2/gpmc-nand.c | 38 ++----
arch/arm/mach-omap2/gpmc-onenand.c | 2 +-
arch/arm/mach-omap2/gpmc.c | 244 ++++++++++++++++++++++++----
arch/arm/plat-omap/include/plat/gpmc.h | 36 ++++-
arch/arm/plat-omap/include/plat/nand.h | 6 +-
drivers/mtd/nand/omap2.c | 190 ++++++----------------
11 files changed, 301 insertions(+), 252 deletions(-)
diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c
index f4e8063..87bed2a
--- a/arch/arm/mach-omap2/board-cm-t35.c
+++ b/arch/arm/mach-omap2/board-cm-t35.c
@@ -61,8 +61,6 @@
#define SB_T35_SMSC911X_GPIO 65
#define NAND_BLOCK_SIZE SZ_128K
-#define GPMC_CS0_BASE 0x60
-#define GPMC_CS0_BASE_ADDR (OMAP34XX_GPMC_VIRT + GPMC_CS0_BASE)
#if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
#include <linux/smsc911x.h>
@@ -223,8 +221,6 @@ static struct omap_nand_platform_data cm_t35_nand_data = {
.nr_parts = ARRAY_SIZE(cm_t35_nand_partitions),
.dma_channel = -1, /* disable DMA in OMAP NAND driver */
.cs = 0,
- .gpmc_cs_baseaddr = (void __iomem *)GPMC_CS0_BASE_ADDR,
- .gpmc_baseaddr = (void __iomem *)OMAP34XX_GPMC_VIRT,
};
diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c
index 6d910df..ef9b677
--- a/arch/arm/mach-omap2/board-devkit8000.c
+++ b/arch/arm/mach-omap2/board-devkit8000.c
@@ -58,9 +58,6 @@
#include "mux.h"
#include "hsmmc.h"
-#define GPMC_CS0_BASE 0x60
-#define GPMC_CS_SIZE 0x30
-
#define NAND_BLOCK_SIZE SZ_128K
#define OMAP_DM9000_GPIO_IRQ 25
@@ -581,8 +578,6 @@ static void __init devkit8000_flash_init(void)
u8 cs = 0;
u8 nandcs = GPMC_CS_NUM + 1;
- u32 gpmc_base_add = OMAP34XX_GPMC_VIRT;
-
/* find out the chip-select on which NAND exists */
while (cs < GPMC_CS_NUM) {
u32 ret = 0;
@@ -604,10 +599,6 @@ static void __init devkit8000_flash_init(void)
if (nandcs < GPMC_CS_NUM) {
devkit8000_nand_data.cs = nandcs;
- devkit8000_nand_data.gpmc_cs_baseaddr = (void *)
- (gpmc_base_add + GPMC_CS0_BASE + nandcs * GPMC_CS_SIZE);
- devkit8000_nand_data.gpmc_baseaddr = (void *)
- (gpmc_base_add);
printk(KERN_INFO "Registering NAND on CS%d\n", nandcs);
if (platform_device_register(&devkit8000_nand_device) < 0)
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index 5df89f6..e90dd2a
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -47,9 +47,6 @@
#include "mux.h"
#include "hsmmc.h"
-#define GPMC_CS0_BASE 0x60
-#define GPMC_CS_SIZE 0x30
-
#define NAND_BLOCK_SIZE SZ_128K
static struct mtd_partition omap3beagle_nand_partitions[] = {
@@ -377,8 +374,6 @@ static void __init omap3beagle_flash_init(void)
u8 cs = 0;
u8 nandcs = GPMC_CS_NUM + 1;
- u32 gpmc_base_add = OMAP34XX_GPMC_VIRT;
-
/* find out the chip-select on which NAND exists */
while (cs < GPMC_CS_NUM) {
u32 ret = 0;
@@ -400,9 +395,6 @@ static void __init omap3beagle_flash_init(void)
if (nandcs < GPMC_CS_NUM) {
omap3beagle_nand_data.cs = nandcs;
- omap3beagle_nand_data.gpmc_cs_baseaddr = (void *)
- (gpmc_base_add + GPMC_CS0_BASE + nandcs * GPMC_CS_SIZE);
- omap3beagle_nand_data.gpmc_baseaddr = (void *) (gpmc_base_add);
printk(KERN_INFO "Registering NAND on CS%d\n", nandcs);
if (platform_device_register(&omap3beagle_nand_device) < 0)
diff --git a/arch/arm/mach-omap2/board-omap3touchbook.c b/arch/arm/mach-omap2/board-omap3touchbook.c
index c59050d..4a6c984
--- a/arch/arm/mach-omap2/board-omap3touchbook.c
+++ b/arch/arm/mach-omap2/board-omap3touchbook.c
@@ -54,9 +54,6 @@
#include <asm/setup.h>
-#define GPMC_CS0_BASE 0x60
-#define GPMC_CS_SIZE 0x30
-
#define NAND_BLOCK_SIZE SZ_128K
#define OMAP3_AC_GPIO 136
@@ -459,8 +456,6 @@ static void __init omap3touchbook_flash_init(void)
u8 cs = 0;
u8 nandcs = GPMC_CS_NUM + 1;
- u32 gpmc_base_add = OMAP34XX_GPMC_VIRT;
-
/* find out the chip-select on which NAND exists */
while (cs < GPMC_CS_NUM) {
u32 ret = 0;
@@ -482,10 +477,6 @@ static void __init omap3touchbook_flash_init(void)
if (nandcs < GPMC_CS_NUM) {
omap3touchbook_nand_data.cs = nandcs;
- omap3touchbook_nand_data.gpmc_cs_baseaddr = (void *)
- (gpmc_base_add + GPMC_CS0_BASE + nandcs * GPMC_CS_SIZE);
- omap3touchbook_nand_data.gpmc_baseaddr =
- (void *) (gpmc_base_add);
printk(KERN_INFO "Registering NAND on CS%d\n", nandcs);
if (platform_device_register(&omap3touchbook_nand_device) < 0)
diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
index 24b32d7..a9151fb
--- a/arch/arm/mach-omap2/board-overo.c
+++ b/arch/arm/mach-omap2/board-overo.c
@@ -58,8 +58,6 @@
#define OVERO_GPIO_USBH_NRESET 183
#define NAND_BLOCK_SIZE SZ_128K
-#define GPMC_CS0_BASE 0x60
-#define GPMC_CS_SIZE 0x30
#define OVERO_SMSC911X_CS 5
#define OVERO_SMSC911X_GPIO 176
@@ -251,8 +249,6 @@ static void __init overo_flash_init(void)
u8 cs = 0;
u8 nandcs = GPMC_CS_NUM + 1;
- u32 gpmc_base_add = OMAP34XX_GPMC_VIRT;
-
/* find out the chip-select on which NAND exists */
while (cs < GPMC_CS_NUM) {
u32 ret = 0;
@@ -274,9 +270,6 @@ static void __init overo_flash_init(void)
if (nandcs < GPMC_CS_NUM) {
overo_nand_data.cs = nandcs;
- overo_nand_data.gpmc_cs_baseaddr = (void *)
- (gpmc_base_add + GPMC_CS0_BASE + nandcs * GPMC_CS_SIZE);
- overo_nand_data.gpmc_baseaddr = (void *) (gpmc_base_add);
printk(KERN_INFO "Registering NAND on CS%d\n", nandcs);
if (platform_device_register(&overo_nand_device) < 0)
diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c
index e57fb29..8aa74be
--- a/arch/arm/mach-omap2/gpmc-nand.c
+++ b/arch/arm/mach-omap2/gpmc-nand.c
@@ -19,8 +19,6 @@
#include <plat/board.h>
#include <plat/gpmc.h>
-#define WR_RD_PIN_MONITORING 0x00600000
-
static struct omap_nand_platform_data *gpmc_nand_data;
static struct resource gpmc_nand_resource = {
@@ -71,10 +69,10 @@ static int omap2_nand_gpmc_retime(void)
t.wr_cycle = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->wr_cycle);
/* Configure GPMC */
- gpmc_cs_write_reg(gpmc_nand_data->cs, GPMC_CS_CONFIG1,
- GPMC_CONFIG1_DEVICESIZE(gpmc_nand_data->devsize) |
- GPMC_CONFIG1_DEVICETYPE_NAND);
-
+ gpmc_hwcontrol(1, gpmc_nand_data->cs,
+ GPMC_CONFIG_DEV_SIZE, gpmc_nand_data->devsize, NULL);
+ gpmc_hwcontrol(1, gpmc_nand_data->cs,
+ GPMC_CONFIG_DEV_TYPE, GPMC_DEVICETYPE_NAND, NULL);
err = gpmc_cs_set_timings(gpmc_nand_data->cs, &t);
if (err)
return err;
@@ -82,27 +80,13 @@ static int omap2_nand_gpmc_retime(void)
return 0;
}
-static int gpmc_nand_setup(void)
-{
- struct device *dev = &gpmc_nand_device.dev;
-
- /* Set timings in GPMC */
- if (omap2_nand_gpmc_retime() < 0) {
- dev_err(dev, "Unable to set gpmc timings\n");
- return -EINVAL;
- }
-
- return 0;
-}
-
int __init gpmc_nand_init(struct omap_nand_platform_data *_nand_data)
{
- unsigned int val;
int err = 0;
struct device *dev = &gpmc_nand_device.dev;
gpmc_nand_data = _nand_data;
- gpmc_nand_data->nand_setup = gpmc_nand_setup;
+ gpmc_nand_data->nand_setup = omap2_nand_gpmc_retime;
gpmc_nand_device.dev.platform_data = gpmc_nand_data;
err = gpmc_cs_request(gpmc_nand_data->cs, NAND_IO_SIZE,
@@ -112,19 +96,17 @@ int __init gpmc_nand_init(struct omap_nand_platform_data *_nand_data)
return err;
}
- err = gpmc_nand_setup();
+ /* Set timings in GPMC */
+ err = omap2_nand_gpmc_retime();
if (err < 0) {
- dev_err(dev, "NAND platform setup failed: %d\n", err);
+ dev_err(dev, "Unable to set gpmc timings: %d\n", err);
return err;
}
/* Enable RD PIN Monitoring Reg */
if (gpmc_nand_data->dev_ready) {
- val = gpmc_cs_read_reg(gpmc_nand_data->cs,
- GPMC_CS_CONFIG1);
- val |= WR_RD_PIN_MONITORING;
- gpmc_cs_write_reg(gpmc_nand_data->cs,
- GPMC_CS_CONFIG1, val);
+ gpmc_hwcontrol(1, gpmc_nand_data->cs,
+ GPMC_CONFIG_RDY_BSY, 1, NULL);
}
err = platform_device_register(&gpmc_nand_device);
diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c
index 7bb6922..5d66817
--- a/arch/arm/mach-omap2/gpmc-onenand.c
+++ b/arch/arm/mach-omap2/gpmc-onenand.c
@@ -301,7 +301,7 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg,
(GPMC_CONFIG1_WAIT_READ_MON |
GPMC_CONFIG1_WAIT_PIN_SEL(0))) |
GPMC_CONFIG1_DEVICESIZE_16 |
- GPMC_CONFIG1_DEVICETYPE_NOR |
+ GPMC_CONFIG1_DEVICETYPE(GPMC_DEVICETYPE_NOR) |
GPMC_CONFIG1_MUXADDDATA);
err = gpmc_cs_set_timings(cs, &t);
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index 5bc3ca0..a3fd1ed
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -29,27 +29,27 @@
#include <plat/sdrc.h>
/* GPMC register offsets */
-#define GPMC_REVISION 0x00
-#define GPMC_SYSCONFIG 0x10
-#define GPMC_SYSSTATUS 0x14
-#define GPMC_IRQSTATUS 0x18
-#define GPMC_IRQENABLE 0x1c
-#define GPMC_TIMEOUT_CONTROL 0x40
-#define GPMC_ERR_ADDRESS 0x44
-#define GPMC_ERR_TYPE 0x48
-#define GPMC_CONFIG 0x50
-#define GPMC_STATUS 0x54
-#define GPMC_PREFETCH_CONFIG1 0x1e0
-#define GPMC_PREFETCH_CONFIG2 0x1e4
-#define GPMC_PREFETCH_CONTROL 0x1ec
-#define GPMC_PREFETCH_STATUS 0x1f0
-#define GPMC_ECC_CONFIG 0x1f4
-#define GPMC_ECC_CONTROL 0x1f8
-#define GPMC_ECC_SIZE_CONFIG 0x1fc
-
-#define GPMC_CS0 0x60
-#define GPMC_CS_SIZE 0x30
-
+#define GPMC_REVISION 0x00
+#define GPMC_SYSCONFIG 0x10
+#define GPMC_SYSSTATUS 0x14
+#define GPMC_IRQSTATUS 0x18
+#define GPMC_IRQENABLE 0x1c
+#define GPMC_TIMEOUT_CONTROL 0x40
+#define GPMC_ERR_ADDRESS 0x44
+#define GPMC_ERR_TYPE 0x48
+#define GPMC_CONFIG 0x50
+#define GPMC_STATUS 0x54
+#define GPMC_PREFETCH_CONFIG1 0x1e0
+#define GPMC_PREFETCH_CONFIG2 0x1e4
+#define GPMC_PREFETCH_CONTROL 0x1ec
+#define GPMC_PREFETCH_STATUS 0x1f0
+#define GPMC_ECC_CONFIG 0x1f4
+#define GPMC_ECC_CONTROL 0x1f8
+#define GPMC_ECC_SIZE_CONFIG 0x1fc
+#define GPMC_ECC1_RESULT 0x200
+
+#define GPMC_CS0_BASE 0x60
+#define GPMC_CS_SIZE 0x30
#define GPMC_MEM_START 0x00000000
#define GPMC_MEM_END 0x3FFFFFFF
#define BOOT_ROM_SPACE 0x100000 /* 1MB */
@@ -108,11 +108,27 @@ static u32 gpmc_read_reg(int idx)
return __raw_readl(gpmc_base + idx);
}
+static void gpmc_cs_write_byte(int cs, int idx, u8 val)
+{
+ void __iomem *reg_addr;
+
+ reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx;
+ __raw_writeb(val, reg_addr);
+}
+
+static u8 gpmc_cs_read_byte(int cs, int idx)
+{
+ void __iomem *reg_addr;
+
+ reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx;
+ return __raw_readb(reg_addr);
+}
+
void gpmc_cs_write_reg(int cs, int idx, u32 val)
{
void __iomem *reg_addr;
- reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx;
+ reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx;
__raw_writel(val, reg_addr);
}
@@ -120,7 +136,7 @@ u32 gpmc_cs_read_reg(int cs, int idx)
{
void __iomem *reg_addr;
- reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx;
+ reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx;
return __raw_readl(reg_addr);
}
@@ -419,6 +435,96 @@ void gpmc_cs_free(int cs)
EXPORT_SYMBOL(gpmc_cs_free);
/**
+ * gpmc_hwcontrol - hardware specific access (read/ write) to control
+ * @write: need 1 for configure; 0 for reading the complete register
+ * @cs: chip select number
+ * @cmd: Command type
+ * @wval: value/information to write
+ * @rval: pointer to get the value back
+ */
+int gpmc_hwcontrol(int write, int cs, int cmd, int wval, int *rval)
+{
+ u32 reg = 0;
+ u32 regval = 0;
+
+ switch (cmd) {
+
+ case GPMC_GET_SET_STATUS:
+ reg = GPMC_STATUS;
+ if (write)
+ gpmc_write_reg(GPMC_STATUS, regval);
+ break;
+
+ case GPMC_GET_SET_IRQ_STATUS:
+ reg = GPMC_IRQSTATUS;
+ if (write)
+ gpmc_write_reg(GPMC_IRQSTATUS, regval);
+ break;
+
+ case GPMC_GET_PREF_STATUS:
+ reg = GPMC_PREFETCH_STATUS;
+ break;
+
+ case GPMC_CONFIG_WP:
+ reg = GPMC_CONFIG;
+ regval = gpmc_read_reg(GPMC_CONFIG);
+ if (wval)
+ regval &= ~GPMC_CONFIG_WRITEPROTECT; /* WP is ON */
+ else
+ regval |= GPMC_CONFIG_WRITEPROTECT; /* WP is OFF */
+ gpmc_write_reg(reg, regval);
+ break;
+
+ case GPMC_CONFIG_RDY_BSY:
+ #define WR_RD_PIN_MONITORING 0x00600000
+ regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
+ regval |= WR_RD_PIN_MONITORING;
+ gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
+ break;
+
+ case GPMC_CONFIG_DEV_SIZE:
+ regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
+ regval |= GPMC_CONFIG1_DEVICESIZE(wval);
+ gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
+ break;
+
+ case GPMC_CONFIG_DEV_TYPE:
+ regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
+ regval |= GPMC_CONFIG1_DEVICETYPE(wval);
+ if (wval == GPMC_DEVICETYPE_NOR)
+ regval |= GPMC_CONFIG1_MUXADDDATA;
+ gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
+ break;
+
+ case GPMC_NAND_COMMAND:
+ gpmc_cs_write_byte(cs, GPMC_CS_NAND_COMMAND, wval);
+ break;
+
+ case GPMC_NAND_ADDRESS:
+ gpmc_cs_write_byte(cs, GPMC_CS_NAND_ADDRESS, wval);
+ break;
+
+ case GPMC_NAND_DATA:
+ if (write)
+ gpmc_cs_write_byte(cs, GPMC_CS_NAND_DATA, wval);
+ else
+ *rval = gpmc_cs_read_byte(cs, GPMC_CS_NAND_DATA);
+ break;
+
+ default:
+ dump_stack();
+ printk(KERN_ERR "not supported\n");
+ return -1;
+ }
+
+ if (!write && reg)
+ *rval = gpmc_read_reg(reg);
+
+ return 0;
+}
+EXPORT_SYMBOL(gpmc_hwcontrol);
+
+/**
* gpmc_prefetch_enable - configures and starts prefetch transfer
* @cs: nand cs (chip select) number
* @dma_mode: dma mode enable (1) or disable (0)
@@ -466,15 +572,6 @@ void gpmc_prefetch_reset(void)
}
EXPORT_SYMBOL(gpmc_prefetch_reset);
-/**
- * gpmc_prefetch_status - reads prefetch status of engine
- */
-int gpmc_prefetch_status(void)
-{
- return gpmc_read_reg(GPMC_PREFETCH_STATUS);
-}
-EXPORT_SYMBOL(gpmc_prefetch_status);
-
static void __init gpmc_mem_init(void)
{
int cs;
@@ -615,3 +712,86 @@ void omap3_gpmc_restore_context(void)
}
}
#endif /* CONFIG_ARCH_OMAP3 */
+
+/**
+ * gmpc_ecc_init - Initialize the HW ECC for NAND flash in GPMC controller
+ * @cs: Chip select number
+ * @ecc_size: bytes for which ECC will be generated
+ */
+void gpmc_ecc_init(int cs, int ecc_size)
+{
+ unsigned int val = 0x0;
+
+ /* Read from ECC Control Register */
+ val = gpmc_read_reg(GPMC_ECC_CONTROL);
+
+ /* Clear all ECC | Enable Reg1 */
+ val = ((0x00000001<<8) | 0x00000001);
+ gpmc_write_reg(GPMC_ECC_CONTROL, val);
+
+ /* Read from ECC Size Config Register */
+ val = gpmc_read_reg(GPMC_ECC_SIZE_CONFIG);
+ /* ECCSIZE1=512 | Select eccResultsize[0-3] */
+ val = ((((ecc_size >> 1) - 1) << 22) | (0x0000000F));
+ gpmc_write_reg(GPMC_ECC_SIZE_CONFIG, val);
+}
+
+/**
+ * gpmc_calcuate_ecc - Generate non-inverted ECC bytes.
+ * @cs: Chip select number
+ * @dat: The pointer to data on which ecc is computed
+ * @ecc_code: The ecc_code buffer
+ *
+ * Using noninverted ECC can be considered ugly since writing a blank
+ * page ie. padding will clear the ECC bytes. This is no problem as long
+ * nobody is trying to write data on the seemingly unused page. Reading
+ * an erased page will produce an ECC mismatch between generated and read
+ * ECC bytes that has to be dealt with separately.
+ */
+int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code)
+{
+ unsigned int val = 0x0;
+
+ /* Start Reading from HW ECC1_Result = 0x200 */
+ val = gpmc_read_reg(GPMC_ECC1_RESULT);
+ *ecc_code++ = val; /* P128e, ..., P1e */
+ *ecc_code++ = val >> 16; /* P128o, ..., P1o */
+ /* P2048o, P1024o, P512o, P256o, P2048e, P1024e, P512e, P256e */
+ *ecc_code++ = ((val >> 8) & 0x0f) | ((val >> 20) & 0xf0);
+
+ return 0;
+}
+
+/**
+ * gpmc_enable_hwecc - This function enables the hardware ecc functionality
+ * @cs: Chip select number
+ * @mode: Read/Write mode
+ * @dev_width: device bus width
+ */
+void gpmc_enable_hwecc(int cs, int mode, int dev_width)
+{
+ unsigned int val = gpmc_read_reg(GPMC_ECC_CONFIG);
+
+ switch (mode) {
+ case GPMC_ECC_READ:
+ gpmc_write_reg(GPMC_ECC_CONTROL, 0x101);
+ /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */
+ val = (dev_width << 7) | (cs << 1) | (0x1);
+ break;
+ case GPMC_ECC_READSYN:
+ gpmc_write_reg(GPMC_ECC_CONTROL, 0x100);
+ /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */
+ val = (dev_width << 7) | (cs << 1) | (0x1);
+ break;
+ case GPMC_ECC_WRITE:
+ gpmc_write_reg(GPMC_ECC_CONTROL, 0x101);
+ /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */
+ val = (dev_width << 7) | (cs << 1) | (0x1);
+ break;
+ default:
+ printk(KERN_INFO "Error: Unrecognized Mode[%d]!\n", mode);
+ break;
+ }
+
+ gpmc_write_reg(GPMC_ECC_CONFIG, val);
+}
diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h
index 145838a..56e1407
--- a/arch/arm/plat-omap/include/plat/gpmc.h
+++ b/arch/arm/plat-omap/include/plat/gpmc.h
@@ -25,10 +25,22 @@
#define GPMC_CS_NAND_ADDRESS 0x20
#define GPMC_CS_NAND_DATA 0x24
-#define GPMC_CONFIG 0x50
-#define GPMC_STATUS 0x54
-#define GPMC_CS0_BASE 0x60
-#define GPMC_CS_SIZE 0x30
+/* Control Commands */
+#define GPMC_GET_SET_STATUS 0x00000001
+#define GPMC_CONFIG_WP 0x00000002
+#define GPMC_CONFIG_RDY_BSY 0x00000003
+#define GPMC_CONFIG_DEV_SIZE 0x00000004
+#define GPMC_CONFIG_DEV_TYPE 0x00000005
+#define GPMC_NAND_COMMAND 0x00000006
+#define GPMC_NAND_ADDRESS 0x00000007
+#define GPMC_NAND_DATA 0x00000008
+#define GPMC_GET_PREF_STATUS 0x00000009
+#define GPMC_GET_SET_IRQ_STATUS 0x0000000a
+
+/* ECC commands */
+#define GPMC_ECC_READ 0 /* Reset Hardware ECC for read */
+#define GPMC_ECC_WRITE 1 /* Reset Hardware ECC for write */
+#define GPMC_ECC_READSYN 2 /* Reset before syndrom is read back */
#define GPMC_CONFIG1_WRAPBURST_SUPP (1 << 31)
#define GPMC_CONFIG1_READMULTIPLE_SUPP (1 << 30)
@@ -44,10 +56,7 @@
#define GPMC_CONFIG1_WAIT_MON_IIME(val) ((val & 3) << 18)
#define GPMC_CONFIG1_WAIT_PIN_SEL(val) ((val & 3) << 16)
#define GPMC_CONFIG1_DEVICESIZE(val) ((val & 3) << 12)
-#define GPMC_CONFIG1_DEVICESIZE_16 GPMC_CONFIG1_DEVICESIZE(1)
#define GPMC_CONFIG1_DEVICETYPE(val) ((val & 3) << 10)
-#define GPMC_CONFIG1_DEVICETYPE_NOR GPMC_CONFIG1_DEVICETYPE(0)
-#define GPMC_CONFIG1_DEVICETYPE_NAND GPMC_CONFIG1_DEVICETYPE(2)
#define GPMC_CONFIG1_MUXADDDATA (1 << 9)
#define GPMC_CONFIG1_TIME_PARA_GRAN (1 << 4)
#define GPMC_CONFIG1_FCLK_DIV(val) (val & 3)
@@ -56,6 +65,12 @@
#define GPMC_CONFIG1_FCLK_DIV4 (GPMC_CONFIG1_FCLK_DIV(3))
#define GPMC_CONFIG7_CSVALID (1 << 6)
+#define GPMC_DEVICETYPE_NOR 0
+#define GPMC_DEVICETYPE_NAND 2
+#define GPMC_CONFIG_WRITEPROTECT 0x00000010
+#define GPMC_CONFIG1_DEVICESIZE_16 GPMC_CONFIG1_DEVICESIZE(1)
+
+
/*
* Note that all values in this struct are in nanoseconds, while
* the register values are in gpmc_fck cycles.
@@ -109,9 +124,14 @@ extern int gpmc_cs_reserved(int cs);
extern int gpmc_prefetch_enable(int cs, int dma_mode,
unsigned int u32_count, int is_write);
extern void gpmc_prefetch_reset(void);
-extern int gpmc_prefetch_status(void);
extern void omap3_gpmc_save_context(void);
extern void omap3_gpmc_restore_context(void);
extern void gpmc_init(void);
+extern int gpmc_hwcontrol(int write, int cs, int cmd, int wval, int *rval);
+
+void gpmc_ecc_init(int cs, int ecc_size);
+void gpmc_enable_hwecc(int cs, int mode, int dev_width);
+int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code);
+
#endif
diff --git a/arch/arm/plat-omap/include/plat/nand.h b/arch/arm/plat-omap/include/plat/nand.h
index f8efd54..6562cd0
--- a/arch/arm/plat-omap/include/plat/nand.h
+++ b/arch/arm/plat-omap/include/plat/nand.h
@@ -21,13 +21,11 @@ struct omap_nand_platform_data {
int (*dev_ready)(struct omap_nand_platform_data *);
int dma_channel;
unsigned long phys_base;
- void __iomem *gpmc_cs_baseaddr;
- void __iomem *gpmc_baseaddr;
int devsize;
};
-/* size (4 KiB) for IO mapping */
-#define NAND_IO_SIZE SZ_4K
+/* minimum size for IO mapping */
+#define NAND_IO_SIZE 4
#if defined(CONFIG_MTD_NAND_OMAP2) || defined(CONFIG_MTD_NAND_OMAP2_MODULE)
extern int gpmc_nand_init(struct omap_nand_platform_data *d);
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 7545568..1858c42
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -23,12 +23,6 @@
#include <plat/gpmc.h>
#include <plat/nand.h>
-#define GPMC_IRQ_STATUS 0x18
-#define GPMC_ECC_CONFIG 0x1F4
-#define GPMC_ECC_CONTROL 0x1F8
-#define GPMC_ECC_SIZE_CONFIG 0x1FC
-#define GPMC_ECC1_RESULT 0x200
-
#define DRIVER_NAME "omap2-nand"
#define NAND_WP_OFF 0
@@ -37,6 +31,7 @@
#define GPMC_BUF_FULL 0x00000001
#define GPMC_BUF_EMPTY 0x00000000
+#ifdef CONFIG_MTD_NAND_OMAP_HWECC
#define NAND_Ecc_P1e (1 << 0)
#define NAND_Ecc_P2e (1 << 1)
#define NAND_Ecc_P4e (1 << 2)
@@ -103,6 +98,7 @@
#define P4e_s(a) (TF(a & NAND_Ecc_P4e) << 0)
#define P4o_s(a) (TF(a & NAND_Ecc_P4o) << 1)
+#endif /* CONFIG_MTD_NAND_OMAP_HWECC */
#ifdef CONFIG_MTD_PARTITIONS
static const char *part_probes[] = { "cmdlinepart", NULL };
@@ -139,34 +135,11 @@ struct omap_nand_info {
int gpmc_cs;
unsigned long phys_base;
- void __iomem *gpmc_cs_baseaddr;
- void __iomem *gpmc_baseaddr;
- void __iomem *nand_pref_fifo_add;
struct completion comp;
int dma_ch;
};
/**
- * omap_nand_wp - This function enable or disable the Write Protect feature
- * @mtd: MTD device structure
- * @mode: WP ON/OFF
- */
-static void omap_nand_wp(struct mtd_info *mtd, int mode)
-{
- struct omap_nand_info *info = container_of(mtd,
- struct omap_nand_info, mtd);
-
- unsigned long config = __raw_readl(info->gpmc_baseaddr + GPMC_CONFIG);
-
- if (mode)
- config &= ~(NAND_WP_BIT); /* WP is ON */
- else
- config |= (NAND_WP_BIT); /* WP is OFF */
-
- __raw_writel(config, (info->gpmc_baseaddr + GPMC_CONFIG));
-}
-
-/**
* omap_hwcontrol - hardware specific access to control-lines
* @mtd: MTD device structure
* @cmd: command to device
@@ -181,31 +154,20 @@ static void omap_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
struct omap_nand_info *info = container_of(mtd,
struct omap_nand_info, mtd);
- switch (ctrl) {
- case NAND_CTRL_CHANGE | NAND_CTRL_CLE:
- info->nand.IO_ADDR_W = info->gpmc_cs_baseaddr +
- GPMC_CS_NAND_COMMAND;
- info->nand.IO_ADDR_R = info->gpmc_cs_baseaddr +
- GPMC_CS_NAND_DATA;
- break;
-
- case NAND_CTRL_CHANGE | NAND_CTRL_ALE:
- info->nand.IO_ADDR_W = info->gpmc_cs_baseaddr +
- GPMC_CS_NAND_ADDRESS;
- info->nand.IO_ADDR_R = info->gpmc_cs_baseaddr +
- GPMC_CS_NAND_DATA;
- break;
-
- case NAND_CTRL_CHANGE | NAND_NCE:
- info->nand.IO_ADDR_W = info->gpmc_cs_baseaddr +
- GPMC_CS_NAND_DATA;
- info->nand.IO_ADDR_R = info->gpmc_cs_baseaddr +
- GPMC_CS_NAND_DATA;
- break;
- }
- if (cmd != NAND_CMD_NONE)
- __raw_writeb(cmd, info->nand.IO_ADDR_W);
+ if (cmd != NAND_CMD_NONE) {
+ if (ctrl & NAND_CLE) {
+ gpmc_hwcontrol(1, info->gpmc_cs,
+ GPMC_NAND_COMMAND, cmd, NULL);
+
+ } else if (ctrl & NAND_ALE) {
+ gpmc_hwcontrol(1, info->gpmc_cs,
+ GPMC_NAND_ADDRESS, cmd, NULL);
+
+ } else /* NAND_NCE */
+ gpmc_hwcontrol(1, info->gpmc_cs,
+ GPMC_NAND_DATA, cmd, NULL);
+ }
}
/**
@@ -229,14 +191,15 @@ static void omap_read_buf8(struct mtd_info *mtd, u_char *buf, int len)
*/
static void omap_write_buf8(struct mtd_info *mtd, const u_char *buf, int len)
{
- struct omap_nand_info *info = container_of(mtd,
- struct omap_nand_info, mtd);
+ u32 status;
+ struct nand_chip *nand = mtd->priv;
u_char *p = (u_char *)buf;
while (len--) {
- iowrite8(*p++, info->nand.IO_ADDR_W);
- while (GPMC_BUF_EMPTY == (readl(info->gpmc_baseaddr +
- GPMC_STATUS) & GPMC_BUF_FULL));
+ iowrite8(*p++, nand->IO_ADDR_W);
+ gpmc_hwcontrol(0, 0, GPMC_GET_SET_STATUS, 0, &status);
+ while (GPMC_BUF_EMPTY == (status & GPMC_BUF_FULL))
+ ;
}
}
@@ -261,18 +224,17 @@ static void omap_read_buf16(struct mtd_info *mtd, u_char *buf, int len)
*/
static void omap_write_buf16(struct mtd_info *mtd, const u_char * buf, int len)
{
- struct omap_nand_info *info = container_of(mtd,
- struct omap_nand_info, mtd);
+ u32 status;
+ struct nand_chip *nand = mtd->priv;
u16 *p = (u16 *) buf;
/* FIXME try bursts of writesw() or DMA ... */
len >>= 1;
while (len--) {
- iowrite16(*p++, info->nand.IO_ADDR_W);
-
- while (GPMC_BUF_EMPTY == (readl(info->gpmc_baseaddr +
- GPMC_STATUS) & GPMC_BUF_FULL))
+ iowrite16(*p++, nand->IO_ADDR_W);
+ gpmc_hwcontrol(0, 0, GPMC_GET_SET_STATUS, 0, &status);
+ while (GPMC_BUF_EMPTY == (status & GPMC_BUF_FULL))
;
}
}
@@ -308,9 +270,10 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len)
omap_read_buf8(mtd, buf, len);
} else {
do {
- pfpw_status = gpmc_prefetch_status();
+ gpmc_hwcontrol(0, info->gpmc_cs,
+ GPMC_GET_PREF_STATUS, 0, &pfpw_status);
r_count = ((pfpw_status >> 24) & 0x7F) >> 2;
- ioread32_rep(info->nand_pref_fifo_add, p, r_count);
+ ioread32_rep(info->nand.IO_ADDR_R, p, r_count);
p += r_count;
len -= r_count << 2;
} while (len);
@@ -351,12 +314,13 @@ static void omap_write_buf_pref(struct mtd_info *mtd,
else
omap_write_buf8(mtd, buf, len);
} else {
- pfpw_status = gpmc_prefetch_status();
+ gpmc_hwcontrol(0, 0, GPMC_GET_PREF_STATUS, 0, &pfpw_status);
while (pfpw_status & 0x3FFF) {
w_count = ((pfpw_status >> 24) & 0x7F) >> 1;
for (i = 0; (i < w_count) && len; i++, len -= 2)
- iowrite16(*p++, info->nand_pref_fifo_add);
- pfpw_status = gpmc_prefetch_status();
+ iowrite16(*p++, info->nand.IO_ADDR_W);
+ gpmc_hwcontrol(0, 0,
+ GPMC_GET_PREF_STATUS, 0, &pfpw_status);
}
/* disable and stop the PFPW engine */
@@ -448,7 +412,7 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr,
/* setup and start DMA using dma_addr */
wait_for_completion(&info->comp);
- while (0x3fff & (prefetch_status = gpmc_prefetch_status()))
+ while (0x3fff & (prefetch_status = gpmc_read_reg(GPMC_PREFETCH_STATUS)))
;
/* disable and stop the PFPW engine */
gpmc_prefetch_reset();
@@ -502,7 +466,7 @@ static void omap_write_buf_dma_pref(struct mtd_info *mtd,
omap_write_buf_pref(mtd, buf, len);
else
/* start transfer in DMA mode */
- omap_nand_dma_transfer(mtd, buf, len, 0x1);
+ omap_nand_dma_transfer(mtd, (u_char *) buf, len, 0x1);
}
/**
@@ -535,22 +499,8 @@ static void omap_hwecc_init(struct mtd_info *mtd)
{
struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
mtd);
- struct nand_chip *chip = mtd->priv;
- unsigned long val = 0x0;
-
- /* Read from ECC Control Register */
- val = __raw_readl(info->gpmc_baseaddr + GPMC_ECC_CONTROL);
- /* Clear all ECC | Enable Reg1 */
- val = ((0x00000001<<8) | 0x00000001);
- __raw_writel(val, info->gpmc_baseaddr + GPMC_ECC_CONTROL);
-
- /* Read from ECC Size Config Register */
- val = __raw_readl(info->gpmc_baseaddr + GPMC_ECC_SIZE_CONFIG);
- /* ECCSIZE1=512 | Select eccResultsize[0-3] */
- val = ((((chip->ecc.size >> 1) - 1) << 22) | (0x0000000F));
- __raw_writel(val, info->gpmc_baseaddr + GPMC_ECC_SIZE_CONFIG);
+ gpmc_ecc_init(info->gpmc_cs, info->nand.ecc.size);
}
-
/**
* gen_true_ecc - This function will generate true ECC value
* @ecc_buf: buffer to store ecc code
@@ -752,21 +702,8 @@ static int omap_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
{
struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
mtd);
- unsigned long val = 0x0;
- unsigned long reg;
-
- /* Start Reading from HW ECC1_Result = 0x200 */
- reg = (unsigned long)(info->gpmc_baseaddr + GPMC_ECC1_RESULT);
- val = __raw_readl(reg);
- *ecc_code++ = val; /* P128e, ..., P1e */
- *ecc_code++ = val >> 16; /* P128o, ..., P1o */
- /* P2048o, P1024o, P512o, P256o, P2048e, P1024e, P512e, P256e */
- *ecc_code++ = ((val >> 8) & 0x0f) | ((val >> 20) & 0xf0);
- reg += 4;
-
- return 0;
+ return gpmc_calculate_ecc(info->gpmc_cs, dat, ecc_code);
}
-
/**
* omap_enable_hwecc - This function enables the hardware ecc functionality
* @mtd: MTD device structure
@@ -778,32 +715,10 @@ static void omap_enable_hwecc(struct mtd_info *mtd, int mode)
mtd);
struct nand_chip *chip = mtd->priv;
unsigned int dev_width = (chip->options & NAND_BUSWIDTH_16) ? 1 : 0;
- unsigned long val = __raw_readl(info->gpmc_baseaddr + GPMC_ECC_CONFIG);
-
- switch (mode) {
- case NAND_ECC_READ:
- __raw_writel(0x101, info->gpmc_baseaddr + GPMC_ECC_CONTROL);
- /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */
- val = (dev_width << 7) | (info->gpmc_cs << 1) | (0x1);
- break;
- case NAND_ECC_READSYN:
- __raw_writel(0x100, info->gpmc_baseaddr + GPMC_ECC_CONTROL);
- /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */
- val = (dev_width << 7) | (info->gpmc_cs << 1) | (0x1);
- break;
- case NAND_ECC_WRITE:
- __raw_writel(0x101, info->gpmc_baseaddr + GPMC_ECC_CONTROL);
- /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */
- val = (dev_width << 7) | (info->gpmc_cs << 1) | (0x1);
- break;
- default:
- DEBUG(MTD_DEBUG_LEVEL0, "Error: Unrecognized Mode[%d]!\n",
- mode);
- break;
- }
- __raw_writel(val, info->gpmc_baseaddr + GPMC_ECC_CONFIG);
+ gpmc_enable_hwecc(info->gpmc_cs, mode, dev_width);
}
+
#endif
/**
@@ -831,14 +746,10 @@ static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip)
else
timeo += (HZ * 20) / 1000;
- this->IO_ADDR_W = (void *) info->gpmc_cs_baseaddr +
- GPMC_CS_NAND_COMMAND;
- this->IO_ADDR_R = (void *) info->gpmc_cs_baseaddr + GPMC_CS_NAND_DATA;
-
- __raw_writeb(NAND_CMD_STATUS & 0xFF, this->IO_ADDR_W);
-
+ gpmc_hwcontrol(1, info->gpmc_cs,
+ GPMC_NAND_COMMAND, (NAND_CMD_STATUS & 0xFF), NULL);
while (time_before(jiffies, timeo)) {
- status = __raw_readb(this->IO_ADDR_R);
+ gpmc_hwcontrol(0, info->gpmc_cs, GPMC_NAND_DATA, 0, &status);
if (status & NAND_STATUS_READY)
break;
cond_resched();
@@ -852,22 +763,20 @@ static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip)
*/
static int omap_dev_ready(struct mtd_info *mtd)
{
- struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
- mtd);
- unsigned int val = __raw_readl(info->gpmc_baseaddr + GPMC_IRQ_STATUS);
+ unsigned int val = 0;
+ gpmc_hwcontrol(0, 0, GPMC_GET_SET_IRQ_STATUS, 0, &val);
if ((val & 0x100) == 0x100) {
/* Clear IRQ Interrupt */
val |= 0x100;
val &= ~(0x0);
- __raw_writel(val, info->gpmc_baseaddr + GPMC_IRQ_STATUS);
+ gpmc_hwcontrol(1, 0, GPMC_GET_SET_IRQ_STATUS, val, NULL);
} else {
unsigned int cnt = 0;
while (cnt++ < 0x1FF) {
if ((val & 0x100) == 0x100)
return 0;
- val = __raw_readl(info->gpmc_baseaddr +
- GPMC_IRQ_STATUS);
+ gpmc_hwcontrol(0, 0, GPMC_GET_SET_IRQ_STATUS, 0, &val);
}
}
@@ -898,8 +807,6 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
info->pdev = pdev;
info->gpmc_cs = pdata->cs;
- info->gpmc_baseaddr = pdata->gpmc_baseaddr;
- info->gpmc_cs_baseaddr = pdata->gpmc_cs_baseaddr;
info->phys_base = pdata->phys_base;
info->mtd.priv = &info->nand;
@@ -910,7 +817,7 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
info->nand.options |= NAND_SKIP_BBTSCAN;
/* NAND write protect off */
- omap_nand_wp(&info->mtd, NAND_WP_OFF);
+ gpmc_hwcontrol(1, info->gpmc_cs, GPMC_CONFIG_WP, 0, NULL);
if (!request_mem_region(info->phys_base, NAND_IO_SIZE,
pdev->dev.driver->name)) {
@@ -946,7 +853,6 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
if (use_prefetch) {
/* copy the virtual address of nand base for fifo access */
- info->nand_pref_fifo_add = info->nand.IO_ADDR_R;
info->nand.read_buf = omap_read_buf_pref;
info->nand.write_buf = omap_write_buf_pref;
@@ -1036,7 +942,7 @@ static int omap_nand_remove(struct platform_device *pdev)
/* Release NAND device, its internal structures and partitions */
nand_release(&info->mtd);
- iounmap(info->nand_pref_fifo_add);
+ iounmap(info->nand.IO_ADDR_R);
kfree(&info->mtd);
return 0;
}
^ permalink raw reply related [flat|nested] 102+ messages in thread
* [PATCH v2 2/2] omap3 nand: fix issue in board file to detect the nand
2010-05-14 15:23 ` [PATCH v2 1/2] omap3 nand: cleanup for not to use GPMC virtual address Sukumar Ghorai
@ 2010-05-14 15:23 ` Sukumar Ghorai
2010-05-14 15:28 ` [PATCH v2 1/2] omap3 nand: cleanup for not to use GPMC virtual address Tony Lindgren
` (2 subsequent siblings)
3 siblings, 0 replies; 102+ messages in thread
From: Sukumar Ghorai @ 2010-05-14 15:23 UTC (permalink / raw)
To: linux-omap
Cc: linux-mtd, tony, sakoman, mike, Artem.Bityutskiy, Sukumar Ghorai
Board file modified to pass the GMPC phys_base address to nand driver. This is
required to adopt the _prob function as in omap2.c
Signed-off-by: Sukumar Ghorai <s-ghorai@ti.com>
---
arch/arm/mach-omap2/board-cm-t35.c | 16 +---------------
arch/arm/mach-omap2/board-devkit8000.c | 16 +---------------
arch/arm/mach-omap2/board-omap3beagle.c | 16 +---------------
arch/arm/mach-omap2/board-omap3touchbook.c | 16 +---------------
arch/arm/mach-omap2/board-overo.c | 17 +----------------
5 files changed, 5 insertions(+), 76 deletions(-)
diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c
index fb23122..0544294
--- a/arch/arm/mach-omap2/board-cm-t35.c
+++ b/arch/arm/mach-omap2/board-cm-t35.c
@@ -224,23 +224,9 @@ static struct omap_nand_platform_data cm_t35_nand_data = {
};
-static struct resource cm_t35_nand_resource = {
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device cm_t35_nand_device = {
- .name = "omap2-nand",
- .id = -1,
- .num_resources = 1,
- .resource = &cm_t35_nand_resource,
- .dev = {
- .platform_data = &cm_t35_nand_data,
- },
-};
-
static void __init cm_t35_init_nand(void)
{
- if (platform_device_register(&cm_t35_nand_device) < 0)
+ if (gpmc_nand_init(&cm_t35_nand_data) < 0)
pr_err("CM-T35: Unable to register NAND device\n");
}
#else
diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c
index ca4e409..9a8135d
--- a/arch/arm/mach-omap2/board-devkit8000.c
+++ b/arch/arm/mach-omap2/board-devkit8000.c
@@ -101,20 +101,6 @@ static struct omap_nand_platform_data devkit8000_nand_data = {
.dma_channel = -1, /* disable DMA in OMAP NAND driver */
};
-static struct resource devkit8000_nand_resource = {
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device devkit8000_nand_device = {
- .name = "omap2-nand",
- .id = -1,
- .dev = {
- .platform_data = &devkit8000_nand_data,
- },
- .num_resources = 1,
- .resource = &devkit8000_nand_resource,
-};
-
static struct omap2_hsmmc_info mmc[] = {
{
.mmc = 1,
@@ -601,7 +587,7 @@ static void __init devkit8000_flash_init(void)
devkit8000_nand_data.cs = nandcs;
printk(KERN_INFO "Registering NAND on CS%d\n", nandcs);
- if (platform_device_register(&devkit8000_nand_device) < 0)
+ if (gpmc_nand_init(&devkit8000_nand_data) < 0)
printk(KERN_ERR "Unable to register NAND device\n");
}
}
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index becaebe..bf31b7c
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -89,20 +89,6 @@ static struct omap_nand_platform_data omap3beagle_nand_data = {
.dev_ready = NULL,
};
-static struct resource omap3beagle_nand_resource = {
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device omap3beagle_nand_device = {
- .name = "omap2-nand",
- .id = -1,
- .dev = {
- .platform_data = &omap3beagle_nand_data,
- },
- .num_resources = 1,
- .resource = &omap3beagle_nand_resource,
-};
-
#include "sdram-micron-mt46h32m32lf-6.h"
static struct omap2_hsmmc_info mmc[] = {
@@ -397,7 +383,7 @@ static void __init omap3beagle_flash_init(void)
omap3beagle_nand_data.cs = nandcs;
printk(KERN_INFO "Registering NAND on CS%d\n", nandcs);
- if (platform_device_register(&omap3beagle_nand_device) < 0)
+ if (gpmc_nand_init(&omap3beagle_nand_data) < 0)
printk(KERN_ERR "Unable to register NAND device\n");
}
}
diff --git a/arch/arm/mach-omap2/board-omap3touchbook.c b/arch/arm/mach-omap2/board-omap3touchbook.c
index d6f1b12..e8ad30c
--- a/arch/arm/mach-omap2/board-omap3touchbook.c
+++ b/arch/arm/mach-omap2/board-omap3touchbook.c
@@ -103,20 +103,6 @@ static struct omap_nand_platform_data omap3touchbook_nand_data = {
.dev_ready = NULL,
};
-static struct resource omap3touchbook_nand_resource = {
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device omap3touchbook_nand_device = {
- .name = "omap2-nand",
- .id = -1,
- .dev = {
- .platform_data = &omap3touchbook_nand_data,
- },
- .num_resources = 1,
- .resource = &omap3touchbook_nand_resource,
-};
-
#include "sdram-micron-mt46h32m32lf-6.h"
static struct omap2_hsmmc_info mmc[] = {
@@ -479,7 +465,7 @@ static void __init omap3touchbook_flash_init(void)
omap3touchbook_nand_data.cs = nandcs;
printk(KERN_INFO "Registering NAND on CS%d\n", nandcs);
- if (platform_device_register(&omap3touchbook_nand_device) < 0)
+ if (gpmc_nand_init(&omap3touchbook_nand_data) < 0)
printk(KERN_ERR "Unable to register NAND device\n");
}
}
diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
index bf2ec32..cddc7ad
--- a/arch/arm/mach-omap2/board-overo.c
+++ b/arch/arm/mach-omap2/board-overo.c
@@ -229,21 +229,6 @@ static struct omap_nand_platform_data overo_nand_data = {
.dma_channel = -1, /* disable DMA in OMAP NAND driver */
};
-static struct resource overo_nand_resource = {
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device overo_nand_device = {
- .name = "omap2-nand",
- .id = -1,
- .dev = {
- .platform_data = &overo_nand_data,
- },
- .num_resources = 1,
- .resource = &overo_nand_resource,
-};
-
-
static void __init overo_flash_init(void)
{
u8 cs = 0;
@@ -272,7 +257,7 @@ static void __init overo_flash_init(void)
overo_nand_data.cs = nandcs;
printk(KERN_INFO "Registering NAND on CS%d\n", nandcs);
- if (platform_device_register(&overo_nand_device) < 0)
+ if (gpmc_nand_init(&overo_nand_data) < 0)
printk(KERN_ERR "Unable to register NAND device\n");
}
}
^ permalink raw reply related [flat|nested] 102+ messages in thread
* Re: [PATCH v2 1/2] omap3 nand: cleanup for not to use GPMC virtual address
2010-05-14 15:23 ` [PATCH v2 1/2] omap3 nand: cleanup for not to use GPMC virtual address Sukumar Ghorai
2010-05-14 15:23 ` [PATCH v2 2/2] omap3 nand: fix issue in board file to detect the nand Sukumar Ghorai
@ 2010-05-14 15:28 ` Tony Lindgren
2010-05-14 18:02 ` Vimal Singh
2010-05-14 23:58 ` Tony Lindgren
3 siblings, 0 replies; 102+ messages in thread
From: Tony Lindgren @ 2010-05-14 15:28 UTC (permalink / raw)
To: Sukumar Ghorai; +Cc: linux-omap, linux-mtd, sakoman, mike, Artem.Bityutskiy
* Sukumar Ghorai <s-ghorai@ti.com> [100514 08:18]:
> Necessary function added in GPMC module and used by nand driver. This is for
> not to use GPMC address directly from nand driver. Also it was passing GPMC
> base address from board files and that is removed.
Great, this is starting to look good! I'll take a closer look today, some
quick comments below.
> --- a/arch/arm/mach-omap2/gpmc.c
> +++ b/arch/arm/mach-omap2/gpmc.c
> @@ -29,27 +29,27 @@
> #include <plat/sdrc.h>
>
> /* GPMC register offsets */
> -#define GPMC_REVISION 0x00
> -#define GPMC_SYSCONFIG 0x10
> -#define GPMC_SYSSTATUS 0x14
> -#define GPMC_IRQSTATUS 0x18
> -#define GPMC_IRQENABLE 0x1c
> -#define GPMC_TIMEOUT_CONTROL 0x40
> -#define GPMC_ERR_ADDRESS 0x44
> -#define GPMC_ERR_TYPE 0x48
> -#define GPMC_CONFIG 0x50
> -#define GPMC_STATUS 0x54
> -#define GPMC_PREFETCH_CONFIG1 0x1e0
> -#define GPMC_PREFETCH_CONFIG2 0x1e4
> -#define GPMC_PREFETCH_CONTROL 0x1ec
> -#define GPMC_PREFETCH_STATUS 0x1f0
> -#define GPMC_ECC_CONFIG 0x1f4
> -#define GPMC_ECC_CONTROL 0x1f8
> -#define GPMC_ECC_SIZE_CONFIG 0x1fc
> -
> -#define GPMC_CS0 0x60
> -#define GPMC_CS_SIZE 0x30
> -
> +#define GPMC_REVISION 0x00
> +#define GPMC_SYSCONFIG 0x10
> +#define GPMC_SYSSTATUS 0x14
> +#define GPMC_IRQSTATUS 0x18
> +#define GPMC_IRQENABLE 0x1c
> +#define GPMC_TIMEOUT_CONTROL 0x40
> +#define GPMC_ERR_ADDRESS 0x44
> +#define GPMC_ERR_TYPE 0x48
> +#define GPMC_CONFIG 0x50
> +#define GPMC_STATUS 0x54
> +#define GPMC_PREFETCH_CONFIG1 0x1e0
> +#define GPMC_PREFETCH_CONFIG2 0x1e4
> +#define GPMC_PREFETCH_CONTROL 0x1ec
> +#define GPMC_PREFETCH_STATUS 0x1f0
> +#define GPMC_ECC_CONFIG 0x1f4
> +#define GPMC_ECC_CONTROL 0x1f8
> +#define GPMC_ECC_SIZE_CONFIG 0x1fc
> +#define GPMC_ECC1_RESULT 0x200
> +
> +#define GPMC_CS0_BASE 0x60
> +#define GPMC_CS_SIZE 0x30
> #define GPMC_MEM_START 0x00000000
> #define GPMC_MEM_END 0x3FFFFFFF
> #define BOOT_ROM_SPACE 0x100000 /* 1MB */
These defines should not be modified that much, looks like some spaces
sneaked in instead of tabs?
Maybe also split this patch into two: First add the new functions,
then remove and convert everything to use the new functions.
Regards,
Tony
^ permalink raw reply [flat|nested] 102+ messages in thread
* Re: [PATCH v2 1/2] omap3 nand: cleanup for not to use GPMC virtual address
2010-05-14 15:23 ` [PATCH v2 1/2] omap3 nand: cleanup for not to use GPMC virtual address Sukumar Ghorai
2010-05-14 15:23 ` [PATCH v2 2/2] omap3 nand: fix issue in board file to detect the nand Sukumar Ghorai
2010-05-14 15:28 ` [PATCH v2 1/2] omap3 nand: cleanup for not to use GPMC virtual address Tony Lindgren
@ 2010-05-14 18:02 ` Vimal Singh
2010-05-17 4:22 ` Ghorai, Sukumar
2010-05-14 23:58 ` Tony Lindgren
3 siblings, 1 reply; 102+ messages in thread
From: Vimal Singh @ 2010-05-14 18:02 UTC (permalink / raw)
To: Sukumar Ghorai; +Cc: linux-omap, Artem.Bityutskiy, tony, sakoman, linux-mtd
On Fri, May 14, 2010 at 8:53 PM, Sukumar Ghorai <s-ghorai@ti.com> wrote:
[...]
> diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c
> index 7bb6922..5d66817
> --- a/arch/arm/mach-omap2/gpmc-onenand.c
> +++ b/arch/arm/mach-omap2/gpmc-onenand.c
> @@ -301,7 +301,7 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg,
> (GPMC_CONFIG1_WAIT_READ_MON |
> GPMC_CONFIG1_WAIT_PIN_SEL(0))) |
> GPMC_CONFIG1_DEVICESIZE_16 |
> - GPMC_CONFIG1_DEVICETYPE_NOR |
> + GPMC_CONFIG1_DEVICETYPE(GPMC_DEVICETYPE_NOR) |
> GPMC_CONFIG1_MUXADDDATA);
Please do not dp OneNAND changes in NAND patch.
> diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
> index 5bc3ca0..a3fd1ed
> --- a/arch/arm/mach-omap2/gpmc.c
> +++ b/arch/arm/mach-omap2/gpmc.c
> @@ -29,27 +29,27 @@
> #include <plat/sdrc.h>
>
> /* GPMC register offsets */
> -#define GPMC_REVISION 0x00
> -#define GPMC_SYSCONFIG 0x10
> -#define GPMC_SYSSTATUS 0x14
> -#define GPMC_IRQSTATUS 0x18
> -#define GPMC_IRQENABLE 0x1c
> -#define GPMC_TIMEOUT_CONTROL 0x40
> -#define GPMC_ERR_ADDRESS 0x44
> -#define GPMC_ERR_TYPE 0x48
> -#define GPMC_CONFIG 0x50
> -#define GPMC_STATUS 0x54
> -#define GPMC_PREFETCH_CONFIG1 0x1e0
> -#define GPMC_PREFETCH_CONFIG2 0x1e4
> -#define GPMC_PREFETCH_CONTROL 0x1ec
> -#define GPMC_PREFETCH_STATUS 0x1f0
> -#define GPMC_ECC_CONFIG 0x1f4
> -#define GPMC_ECC_CONTROL 0x1f8
> -#define GPMC_ECC_SIZE_CONFIG 0x1fc
> -
> -#define GPMC_CS0 0x60
> -#define GPMC_CS_SIZE 0x30
> -
> +#define GPMC_REVISION 0x00
> +#define GPMC_SYSCONFIG 0x10
> +#define GPMC_SYSSTATUS 0x14
> +#define GPMC_IRQSTATUS 0x18
> +#define GPMC_IRQENABLE 0x1c
> +#define GPMC_TIMEOUT_CONTROL 0x40
> +#define GPMC_ERR_ADDRESS 0x44
> +#define GPMC_ERR_TYPE 0x48
> +#define GPMC_CONFIG 0x50
> +#define GPMC_STATUS 0x54
> +#define GPMC_PREFETCH_CONFIG1 0x1e0
> +#define GPMC_PREFETCH_CONFIG2 0x1e4
> +#define GPMC_PREFETCH_CONTROL 0x1ec
> +#define GPMC_PREFETCH_STATUS 0x1f0
> +#define GPMC_ECC_CONFIG 0x1f4
> +#define GPMC_ECC_CONTROL 0x1f8
> +#define GPMC_ECC_SIZE_CONFIG 0x1fc
> +#define GPMC_ECC1_RESULT 0x200
> +
> +#define GPMC_CS0_BASE 0x60
> +#define GPMC_CS_SIZE 0x30
> #define GPMC_MEM_START 0x00000000
> #define GPMC_MEM_END 0x3FFFFFFF
> #define BOOT_ROM_SPACE 0x100000 /* 1MB */
> @@ -108,11 +108,27 @@ static u32 gpmc_read_reg(int idx)
> return __raw_readl(gpmc_base + idx);
> }
>
> +static void gpmc_cs_write_byte(int cs, int idx, u8 val)
> +{
> + void __iomem *reg_addr;
> +
> + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx;
> + __raw_writeb(val, reg_addr);
> +}
> +
> +static u8 gpmc_cs_read_byte(int cs, int idx)
> +{
> + void __iomem *reg_addr;
> +
> + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx;
> + return __raw_readb(reg_addr);
> +}
> +
I do not think we need these functions.
> void gpmc_cs_write_reg(int cs, int idx, u32 val)
> {
> void __iomem *reg_addr;
>
> - reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx;
> + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx;
> __raw_writel(val, reg_addr);
> }
>
> @@ -120,7 +136,7 @@ u32 gpmc_cs_read_reg(int cs, int idx)
> {
> void __iomem *reg_addr;
>
> - reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx;
> + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx;
> return __raw_readl(reg_addr);
> }
>
> @@ -419,6 +435,96 @@ void gpmc_cs_free(int cs)
> EXPORT_SYMBOL(gpmc_cs_free);
>
> /**
> + * gpmc_hwcontrol - hardware specific access (read/ write) to control
> + * @write: need 1 for configure; 0 for reading the complete register
> + * @cs: chip select number
> + * @cmd: Command type
> + * @wval: value/information to write
> + * @rval: pointer to get the value back
> + */
> +int gpmc_hwcontrol(int write, int cs, int cmd, int wval, int *rval)
> +{
> + u32 reg = 0;
> + u32 regval = 0;
> +
> + switch (cmd) {
> +
> + case GPMC_GET_SET_STATUS:
> + reg = GPMC_STATUS;
> + if (write)
> + gpmc_write_reg(GPMC_STATUS, regval);
> + break;
> +
> + case GPMC_GET_SET_IRQ_STATUS:
> + reg = GPMC_IRQSTATUS;
> + if (write)
> + gpmc_write_reg(GPMC_IRQSTATUS, regval);
> + break;
> +
> + case GPMC_GET_PREF_STATUS:
> + reg = GPMC_PREFETCH_STATUS;
> + break;
> +
> + case GPMC_CONFIG_WP:
> + reg = GPMC_CONFIG;
> + regval = gpmc_read_reg(GPMC_CONFIG);
> + if (wval)
> + regval &= ~GPMC_CONFIG_WRITEPROTECT; /* WP is ON */
> + else
> + regval |= GPMC_CONFIG_WRITEPROTECT; /* WP is OFF */
> + gpmc_write_reg(reg, regval);
> + break;
> +
> + case GPMC_CONFIG_RDY_BSY:
> + #define WR_RD_PIN_MONITORING 0x00600000
> + regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
> + regval |= WR_RD_PIN_MONITORING;
> + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
> + break;
> +
> + case GPMC_CONFIG_DEV_SIZE:
> + regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
> + regval |= GPMC_CONFIG1_DEVICESIZE(wval);
> + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
> + break;
> +
> + case GPMC_CONFIG_DEV_TYPE:
> + regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
> + regval |= GPMC_CONFIG1_DEVICETYPE(wval);
> + if (wval == GPMC_DEVICETYPE_NOR)
> + regval |= GPMC_CONFIG1_MUXADDDATA;
> + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
> + break;
> +
> + case GPMC_NAND_COMMAND:
> + gpmc_cs_write_byte(cs, GPMC_CS_NAND_COMMAND, wval);
> + break;
> +
> + case GPMC_NAND_ADDRESS:
> + gpmc_cs_write_byte(cs, GPMC_CS_NAND_ADDRESS, wval);
> + break;
> +
> + case GPMC_NAND_DATA:
> + if (write)
> + gpmc_cs_write_byte(cs, GPMC_CS_NAND_DATA, wval);
> + else
> + *rval = gpmc_cs_read_byte(cs, GPMC_CS_NAND_DATA);
> + break;
> +
> + default:
> + dump_stack();
> + printk(KERN_ERR "not supported\n");
> + return -1;
> + }
> +
> + if (!write && reg)
> + *rval = gpmc_read_reg(reg);
> +
> + return 0;
> +}
> +EXPORT_SYMBOL(gpmc_hwcontrol);
> +
> +/**
> * gpmc_prefetch_enable - configures and starts prefetch transfer
> * @cs: nand cs (chip select) number
> * @dma_mode: dma mode enable (1) or disable (0)
> @@ -466,15 +572,6 @@ void gpmc_prefetch_reset(void)
> }
> EXPORT_SYMBOL(gpmc_prefetch_reset);
>
> -/**
> - * gpmc_prefetch_status - reads prefetch status of engine
> - */
> -int gpmc_prefetch_status(void)
> -{
> - return gpmc_read_reg(GPMC_PREFETCH_STATUS);
> -}
> -EXPORT_SYMBOL(gpmc_prefetch_status);
> -
> static void __init gpmc_mem_init(void)
> {
> int cs;
> @@ -615,3 +712,86 @@ void omap3_gpmc_restore_context(void)
> }
> }
> #endif /* CONFIG_ARCH_OMAP3 */
> +
> +/**
> + * gmpc_ecc_init - Initialize the HW ECC for NAND flash in GPMC controller
> + * @cs: Chip select number
> + * @ecc_size: bytes for which ECC will be generated
> + */
> +void gpmc_ecc_init(int cs, int ecc_size)
> +{
> + unsigned int val = 0x0;
> +
> + /* Read from ECC Control Register */
> + val = gpmc_read_reg(GPMC_ECC_CONTROL);
> +
> + /* Clear all ECC | Enable Reg1 */
> + val = ((0x00000001<<8) | 0x00000001);
> + gpmc_write_reg(GPMC_ECC_CONTROL, val);
> +
> + /* Read from ECC Size Config Register */
> + val = gpmc_read_reg(GPMC_ECC_SIZE_CONFIG);
> + /* ECCSIZE1=512 | Select eccResultsize[0-3] */
> + val = ((((ecc_size >> 1) - 1) << 22) | (0x0000000F));
> + gpmc_write_reg(GPMC_ECC_SIZE_CONFIG, val);
> +}
> +
> +/**
> + * gpmc_calcuate_ecc - Generate non-inverted ECC bytes.
> + * @cs: Chip select number
> + * @dat: The pointer to data on which ecc is computed
> + * @ecc_code: The ecc_code buffer
> + *
> + * Using noninverted ECC can be considered ugly since writing a blank
> + * page ie. padding will clear the ECC bytes. This is no problem as long
> + * nobody is trying to write data on the seemingly unused page. Reading
> + * an erased page will produce an ECC mismatch between generated and read
> + * ECC bytes that has to be dealt with separately.
> + */
> +int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code)
> +{
> + unsigned int val = 0x0;
> +
> + /* Start Reading from HW ECC1_Result = 0x200 */
> + val = gpmc_read_reg(GPMC_ECC1_RESULT);
> + *ecc_code++ = val; /* P128e, ..., P1e */
> + *ecc_code++ = val >> 16; /* P128o, ..., P1o */
> + /* P2048o, P1024o, P512o, P256o, P2048e, P1024e, P512e, P256e */
> + *ecc_code++ = ((val >> 8) & 0x0f) | ((val >> 20) & 0xf0);
> +
> + return 0;
> +}
> +
> +/**
> + * gpmc_enable_hwecc - This function enables the hardware ecc functionality
> + * @cs: Chip select number
> + * @mode: Read/Write mode
> + * @dev_width: device bus width
> + */
> +void gpmc_enable_hwecc(int cs, int mode, int dev_width)
> +{
> + unsigned int val = gpmc_read_reg(GPMC_ECC_CONFIG);
> +
> + switch (mode) {
> + case GPMC_ECC_READ:
> + gpmc_write_reg(GPMC_ECC_CONTROL, 0x101);
> + /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */
> + val = (dev_width << 7) | (cs << 1) | (0x1);
> + break;
> + case GPMC_ECC_READSYN:
> + gpmc_write_reg(GPMC_ECC_CONTROL, 0x100);
> + /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */
> + val = (dev_width << 7) | (cs << 1) | (0x1);
> + break;
> + case GPMC_ECC_WRITE:
> + gpmc_write_reg(GPMC_ECC_CONTROL, 0x101);
> + /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */
> + val = (dev_width << 7) | (cs << 1) | (0x1);
> + break;
> + default:
> + printk(KERN_INFO "Error: Unrecognized Mode[%d]!\n", mode);
> + break;
> + }
> +
> + gpmc_write_reg(GPMC_ECC_CONFIG, val);
> +}
> diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h
> index 145838a..56e1407
> --- a/arch/arm/plat-omap/include/plat/gpmc.h
> +++ b/arch/arm/plat-omap/include/plat/gpmc.h
> @@ -25,10 +25,22 @@
> #define GPMC_CS_NAND_ADDRESS 0x20
> #define GPMC_CS_NAND_DATA 0x24
>
> -#define GPMC_CONFIG 0x50
> -#define GPMC_STATUS 0x54
> -#define GPMC_CS0_BASE 0x60
> -#define GPMC_CS_SIZE 0x30
> +/* Control Commands */
> +#define GPMC_GET_SET_STATUS 0x00000001
> +#define GPMC_CONFIG_WP 0x00000002
> +#define GPMC_CONFIG_RDY_BSY 0x00000003
> +#define GPMC_CONFIG_DEV_SIZE 0x00000004
> +#define GPMC_CONFIG_DEV_TYPE 0x00000005
> +#define GPMC_NAND_COMMAND 0x00000006
> +#define GPMC_NAND_ADDRESS 0x00000007
> +#define GPMC_NAND_DATA 0x00000008
> +#define GPMC_GET_PREF_STATUS 0x00000009
> +#define GPMC_GET_SET_IRQ_STATUS 0x0000000a
> +
> +/* ECC commands */
> +#define GPMC_ECC_READ 0 /* Reset Hardware ECC for read */
> +#define GPMC_ECC_WRITE 1 /* Reset Hardware ECC for write */
> +#define GPMC_ECC_READSYN 2 /* Reset before syndrom is read back */
>
> #define GPMC_CONFIG1_WRAPBURST_SUPP (1 << 31)
> #define GPMC_CONFIG1_READMULTIPLE_SUPP (1 << 30)
> @@ -44,10 +56,7 @@
> #define GPMC_CONFIG1_WAIT_MON_IIME(val) ((val & 3) << 18)
> #define GPMC_CONFIG1_WAIT_PIN_SEL(val) ((val & 3) << 16)
> #define GPMC_CONFIG1_DEVICESIZE(val) ((val & 3) << 12)
> -#define GPMC_CONFIG1_DEVICESIZE_16 GPMC_CONFIG1_DEVICESIZE(1)
> #define GPMC_CONFIG1_DEVICETYPE(val) ((val & 3) << 10)
> -#define GPMC_CONFIG1_DEVICETYPE_NOR GPMC_CONFIG1_DEVICETYPE(0)
> -#define GPMC_CONFIG1_DEVICETYPE_NAND GPMC_CONFIG1_DEVICETYPE(2)
> #define GPMC_CONFIG1_MUXADDDATA (1 << 9)
> #define GPMC_CONFIG1_TIME_PARA_GRAN (1 << 4)
> #define GPMC_CONFIG1_FCLK_DIV(val) (val & 3)
> @@ -56,6 +65,12 @@
> #define GPMC_CONFIG1_FCLK_DIV4 (GPMC_CONFIG1_FCLK_DIV(3))
> #define GPMC_CONFIG7_CSVALID (1 << 6)
>
> +#define GPMC_DEVICETYPE_NOR 0
> +#define GPMC_DEVICETYPE_NAND 2
> +#define GPMC_CONFIG_WRITEPROTECT 0x00000010
> +#define GPMC_CONFIG1_DEVICESIZE_16 GPMC_CONFIG1_DEVICESIZE(1)
> +
> +
> /*
> * Note that all values in this struct are in nanoseconds, while
> * the register values are in gpmc_fck cycles.
> @@ -109,9 +124,14 @@ extern int gpmc_cs_reserved(int cs);
> extern int gpmc_prefetch_enable(int cs, int dma_mode,
> unsigned int u32_count, int is_write);
> extern void gpmc_prefetch_reset(void);
> -extern int gpmc_prefetch_status(void);
> extern void omap3_gpmc_save_context(void);
> extern void omap3_gpmc_restore_context(void);
> extern void gpmc_init(void);
> +extern int gpmc_hwcontrol(int write, int cs, int cmd, int wval, int *rval);
> +
> +void gpmc_ecc_init(int cs, int ecc_size);
> +void gpmc_enable_hwecc(int cs, int mode, int dev_width);
> +int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code);
> +
>
> #endif
> diff --git a/arch/arm/plat-omap/include/plat/nand.h b/arch/arm/plat-omap/include/plat/nand.h
> index f8efd54..6562cd0
> --- a/arch/arm/plat-omap/include/plat/nand.h
> +++ b/arch/arm/plat-omap/include/plat/nand.h
> @@ -21,13 +21,11 @@ struct omap_nand_platform_data {
> int (*dev_ready)(struct omap_nand_platform_data *);
> int dma_channel;
> unsigned long phys_base;
> - void __iomem *gpmc_cs_baseaddr;
> - void __iomem *gpmc_baseaddr;
> int devsize;
> };
>
> -/* size (4 KiB) for IO mapping */
> -#define NAND_IO_SIZE SZ_4K
> +/* minimum size for IO mapping */
> +#define NAND_IO_SIZE 4
>
> #if defined(CONFIG_MTD_NAND_OMAP2) || defined(CONFIG_MTD_NAND_OMAP2_MODULE)
> extern int gpmc_nand_init(struct omap_nand_platform_data *d);
> diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
> index 7545568..1858c42
> --- a/drivers/mtd/nand/omap2.c
> +++ b/drivers/mtd/nand/omap2.c
> @@ -23,12 +23,6 @@
> #include <plat/gpmc.h>
> #include <plat/nand.h>
>
> -#define GPMC_IRQ_STATUS 0x18
> -#define GPMC_ECC_CONFIG 0x1F4
> -#define GPMC_ECC_CONTROL 0x1F8
> -#define GPMC_ECC_SIZE_CONFIG 0x1FC
> -#define GPMC_ECC1_RESULT 0x200
> -
> #define DRIVER_NAME "omap2-nand"
>
> #define NAND_WP_OFF 0
> @@ -37,6 +31,7 @@
> #define GPMC_BUF_FULL 0x00000001
> #define GPMC_BUF_EMPTY 0x00000000
>
> +#ifdef CONFIG_MTD_NAND_OMAP_HWECC
> #define NAND_Ecc_P1e (1 << 0)
> #define NAND_Ecc_P2e (1 << 1)
> #define NAND_Ecc_P4e (1 << 2)
> @@ -103,6 +98,7 @@
>
> #define P4e_s(a) (TF(a & NAND_Ecc_P4e) << 0)
> #define P4o_s(a) (TF(a & NAND_Ecc_P4o) << 1)
> +#endif /* CONFIG_MTD_NAND_OMAP_HWECC */
Why this ifdef macro?
>
> #ifdef CONFIG_MTD_PARTITIONS
> static const char *part_probes[] = { "cmdlinepart", NULL };
> @@ -139,34 +135,11 @@ struct omap_nand_info {
>
> int gpmc_cs;
> unsigned long phys_base;
> - void __iomem *gpmc_cs_baseaddr;
> - void __iomem *gpmc_baseaddr;
> - void __iomem *nand_pref_fifo_add;
> struct completion comp;
> int dma_ch;
> };
>
> /**
> - * omap_nand_wp - This function enable or disable the Write Protect feature
> - * @mtd: MTD device structure
> - * @mode: WP ON/OFF
> - */
> -static void omap_nand_wp(struct mtd_info *mtd, int mode)
> -{
> - struct omap_nand_info *info = container_of(mtd,
> - struct omap_nand_info, mtd);
> -
> - unsigned long config = __raw_readl(info->gpmc_baseaddr + GPMC_CONFIG);
> -
> - if (mode)
> - config &= ~(NAND_WP_BIT); /* WP is ON */
> - else
> - config |= (NAND_WP_BIT); /* WP is OFF */
> -
> - __raw_writel(config, (info->gpmc_baseaddr + GPMC_CONFIG));
> -}
> -
> -/**
> * omap_hwcontrol - hardware specific access to control-lines
> * @mtd: MTD device structure
> * @cmd: command to device
> @@ -181,31 +154,20 @@ static void omap_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
> {
> struct omap_nand_info *info = container_of(mtd,
> struct omap_nand_info, mtd);
> - switch (ctrl) {
> - case NAND_CTRL_CHANGE | NAND_CTRL_CLE:
> - info->nand.IO_ADDR_W = info->gpmc_cs_baseaddr +
> - GPMC_CS_NAND_COMMAND;
> - info->nand.IO_ADDR_R = info->gpmc_cs_baseaddr +
> - GPMC_CS_NAND_DATA;
> - break;
> -
> - case NAND_CTRL_CHANGE | NAND_CTRL_ALE:
> - info->nand.IO_ADDR_W = info->gpmc_cs_baseaddr +
> - GPMC_CS_NAND_ADDRESS;
> - info->nand.IO_ADDR_R = info->gpmc_cs_baseaddr +
> - GPMC_CS_NAND_DATA;
> - break;
> -
> - case NAND_CTRL_CHANGE | NAND_NCE:
> - info->nand.IO_ADDR_W = info->gpmc_cs_baseaddr +
> - GPMC_CS_NAND_DATA;
> - info->nand.IO_ADDR_R = info->gpmc_cs_baseaddr +
> - GPMC_CS_NAND_DATA;
> - break;
> - }
>
> - if (cmd != NAND_CMD_NONE)
> - __raw_writeb(cmd, info->nand.IO_ADDR_W);
> + if (cmd != NAND_CMD_NONE) {
> + if (ctrl & NAND_CLE) {
> + gpmc_hwcontrol(1, info->gpmc_cs,
> + GPMC_NAND_COMMAND, cmd, NULL);
> +
> + } else if (ctrl & NAND_ALE) {
> + gpmc_hwcontrol(1, info->gpmc_cs,
> + GPMC_NAND_ADDRESS, cmd, NULL);
> +
> + } else /* NAND_NCE */
> + gpmc_hwcontrol(1, info->gpmc_cs,
> + GPMC_NAND_DATA, cmd, NULL);
> + }
> }
>
> /**
> @@ -229,14 +191,15 @@ static void omap_read_buf8(struct mtd_info *mtd, u_char *buf, int len)
> */
> static void omap_write_buf8(struct mtd_info *mtd, const u_char *buf, int len)
> {
> - struct omap_nand_info *info = container_of(mtd,
> - struct omap_nand_info, mtd);
> + u32 status;
> + struct nand_chip *nand = mtd->priv;
> u_char *p = (u_char *)buf;
>
> while (len--) {
> - iowrite8(*p++, info->nand.IO_ADDR_W);
> - while (GPMC_BUF_EMPTY == (readl(info->gpmc_baseaddr +
> - GPMC_STATUS) & GPMC_BUF_FULL));
> + iowrite8(*p++, nand->IO_ADDR_W);
> + gpmc_hwcontrol(0, 0, GPMC_GET_SET_STATUS, 0, &status);
If I am not mistaking, 2nd argument is 'cs', correct? And then, why
are you hard coding this?
Different boards will have NAND chip present at different 'cs'.
Please have a look at uses of 'gpmc_hwcontrol' elsewhere as well for this.
Again, say, you got '(status & GPMC_BUF_FULL) != GPMC_BUF_EMPTY', then:
> + while (GPMC_BUF_EMPTY == (status & GPMC_BUF_FULL))
> + ;
You got in an infinite loop here?
> }
> }
>
> @@ -261,18 +224,17 @@ static void omap_read_buf16(struct mtd_info *mtd, u_char *buf, int len)
> */
> static void omap_write_buf16(struct mtd_info *mtd, const u_char * buf, int len)
> {
> - struct omap_nand_info *info = container_of(mtd,
> - struct omap_nand_info, mtd);
> + u32 status;
> + struct nand_chip *nand = mtd->priv;
> u16 *p = (u16 *) buf;
>
> /* FIXME try bursts of writesw() or DMA ... */
> len >>= 1;
>
> while (len--) {
> - iowrite16(*p++, info->nand.IO_ADDR_W);
> -
> - while (GPMC_BUF_EMPTY == (readl(info->gpmc_baseaddr +
> - GPMC_STATUS) & GPMC_BUF_FULL))
> + iowrite16(*p++, nand->IO_ADDR_W);
> + gpmc_hwcontrol(0, 0, GPMC_GET_SET_STATUS, 0, &status);
> + while (GPMC_BUF_EMPTY == (status & GPMC_BUF_FULL))
same as above.
--
Regards,
Vimal Singh
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 102+ messages in thread
* Re: [PATCH v2 1/2] omap3 nand: cleanup for not to use GPMC virtual address
2010-05-14 15:23 ` [PATCH v2 1/2] omap3 nand: cleanup for not to use GPMC virtual address Sukumar Ghorai
` (2 preceding siblings ...)
2010-05-14 18:02 ` Vimal Singh
@ 2010-05-14 23:58 ` Tony Lindgren
2010-05-17 5:48 ` Ghorai, Sukumar
3 siblings, 1 reply; 102+ messages in thread
From: Tony Lindgren @ 2010-05-14 23:58 UTC (permalink / raw)
To: Sukumar Ghorai; +Cc: linux-omap, linux-mtd, sakoman, mike, Artem.Bityutskiy
Few more comments below.
* Sukumar Ghorai <s-ghorai@ti.com> [100514 08:18]:
> +
> +/**
> + * gmpc_ecc_init - Initialize the HW ECC for NAND flash in GPMC controller
> + * @cs: Chip select number
> + * @ecc_size: bytes for which ECC will be generated
> + */
> +void gpmc_ecc_init(int cs, int ecc_size)
> +{
> + unsigned int val = 0x0;
> +
> + /* Read from ECC Control Register */
> + val = gpmc_read_reg(GPMC_ECC_CONTROL);
> +
> + /* Clear all ECC | Enable Reg1 */
> + val = ((0x00000001<<8) | 0x00000001);
> + gpmc_write_reg(GPMC_ECC_CONTROL, val);
> +
> + /* Read from ECC Size Config Register */
> + val = gpmc_read_reg(GPMC_ECC_SIZE_CONFIG);
> + /* ECCSIZE1=512 | Select eccResultsize[0-3] */
> + val = ((((ecc_size >> 1) - 1) << 22) | (0x0000000F));
> + gpmc_write_reg(GPMC_ECC_SIZE_CONFIG, val);
> +}
There should be some locking as only one chipselect can use
the ECC or prefetch engine at a time. If you have NAND in
two chipselects, bad things would happen..
Maybe something like:
int gpmc_ecc_request(int cs);
void gpmc_ecc_free(int cs);
int gpmc_prefetch_request(int cs);
void gpmc_prefetch_free(int cs);
Other than that, looks like a good clean-up so we can easily
add the platform init code for all the board files.
Regards,
Tony
^ permalink raw reply [flat|nested] 102+ messages in thread
* RE: [PATCH v2 1/2] omap3 nand: cleanup for not to use GPMC virtual address
2010-05-14 18:02 ` Vimal Singh
@ 2010-05-17 4:22 ` Ghorai, Sukumar
2010-05-17 14:26 ` Vimal Singh
0 siblings, 1 reply; 102+ messages in thread
From: Ghorai, Sukumar @ 2010-05-17 4:22 UTC (permalink / raw)
To: Vimal Singh
Cc: linux-omap@vger.kernel.org, Artem.Bityutskiy@nokia.com,
tony@atomide.com, sakoman@gmail.com,
linux-mtd@lists.infradead.org
Vimal,
> -----Original Message-----
> From: Vimal Singh [mailto:vimal.newwork@gmail.com]
> Sent: 2010-05-14 23:33
> To: Ghorai, Sukumar
> Cc: linux-omap@vger.kernel.org; Artem.Bityutskiy@nokia.com;
> tony@atomide.com; sakoman@gmail.com; linux-mtd@lists.infradead.org
> Subject: Re: [PATCH v2 1/2] omap3 nand: cleanup for not to use GPMC
> virtual address
>
> On Fri, May 14, 2010 at 8:53 PM, Sukumar Ghorai <s-ghorai@ti.com> wrote:
> [...]
>
> > diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-
> omap2/gpmc-onenand.c
> > index 7bb6922..5d66817
> > --- a/arch/arm/mach-omap2/gpmc-onenand.c
> > +++ b/arch/arm/mach-omap2/gpmc-onenand.c
> > @@ -301,7 +301,7 @@ static int omap2_onenand_set_sync_mode(struct
> omap_onenand_platform_data *cfg,
> > (GPMC_CONFIG1_WAIT_READ_MON |
> > GPMC_CONFIG1_WAIT_PIN_SEL(0))) |
> > GPMC_CONFIG1_DEVICESIZE_16 |
> > - GPMC_CONFIG1_DEVICETYPE_NOR |
> > + GPMC_CONFIG1_DEVICETYPE(GPMC_DEVICETYPE_NOR) |
> > GPMC_CONFIG1_MUXADDDATA);
>
> Please do not dp OneNAND changes in NAND patch.
[Ghorai] I agree.
>
> > diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
> > index 5bc3ca0..a3fd1ed
> > --- a/arch/arm/mach-omap2/gpmc.c
> > +++ b/arch/arm/mach-omap2/gpmc.c
> > @@ -29,27 +29,27 @@
> > #include <plat/sdrc.h>
> >
> > /* GPMC register offsets */
> > -#define GPMC_REVISION 0x00
> > -#define GPMC_SYSCONFIG 0x10
> > -#define GPMC_SYSSTATUS 0x14
> > -#define GPMC_IRQSTATUS 0x18
> > -#define GPMC_IRQENABLE 0x1c
> > -#define GPMC_TIMEOUT_CONTROL 0x40
> > -#define GPMC_ERR_ADDRESS 0x44
> > -#define GPMC_ERR_TYPE 0x48
> > -#define GPMC_CONFIG 0x50
> > -#define GPMC_STATUS 0x54
> > -#define GPMC_PREFETCH_CONFIG1 0x1e0
> > -#define GPMC_PREFETCH_CONFIG2 0x1e4
> > -#define GPMC_PREFETCH_CONTROL 0x1ec
> > -#define GPMC_PREFETCH_STATUS 0x1f0
> > -#define GPMC_ECC_CONFIG 0x1f4
> > -#define GPMC_ECC_CONTROL 0x1f8
> > -#define GPMC_ECC_SIZE_CONFIG 0x1fc
> > -
> > -#define GPMC_CS0 0x60
> > -#define GPMC_CS_SIZE 0x30
> > -
> > +#define GPMC_REVISION 0x00
> > +#define GPMC_SYSCONFIG 0x10
> > +#define GPMC_SYSSTATUS 0x14
> > +#define GPMC_IRQSTATUS 0x18
> > +#define GPMC_IRQENABLE 0x1c
> > +#define GPMC_TIMEOUT_CONTROL 0x40
> > +#define GPMC_ERR_ADDRESS 0x44
> > +#define GPMC_ERR_TYPE 0x48
> > +#define GPMC_CONFIG 0x50
> > +#define GPMC_STATUS 0x54
> > +#define GPMC_PREFETCH_CONFIG1 0x1e0
> > +#define GPMC_PREFETCH_CONFIG2 0x1e4
> > +#define GPMC_PREFETCH_CONTROL 0x1ec
> > +#define GPMC_PREFETCH_STATUS 0x1f0
> > +#define GPMC_ECC_CONFIG 0x1f4
> > +#define GPMC_ECC_CONTROL 0x1f8
> > +#define GPMC_ECC_SIZE_CONFIG 0x1fc
> > +#define GPMC_ECC1_RESULT 0x200
> > +
> > +#define GPMC_CS0_BASE 0x60
> > +#define GPMC_CS_SIZE 0x30
> > #define GPMC_MEM_START 0x00000000
> > #define GPMC_MEM_END 0x3FFFFFFF
> > #define BOOT_ROM_SPACE 0x100000 /* 1MB */
> > @@ -108,11 +108,27 @@ static u32 gpmc_read_reg(int idx)
> > return __raw_readl(gpmc_base + idx);
> > }
> >
> > +static void gpmc_cs_write_byte(int cs, int idx, u8 val)
> > +{
> > + void __iomem *reg_addr;
> > +
> > + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) +
> idx;
> > + __raw_writeb(val, reg_addr);
> > +}
> > +
> > +static u8 gpmc_cs_read_byte(int cs, int idx)
> > +{
> > + void __iomem *reg_addr;
> > +
> > + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) +
> idx;
> > + return __raw_readb(reg_addr);
> > +}
> > +
>
> I do not think we need these functions.
[Ghorai] This is used in gpmc_hwcontrol() and to get the nand status from omap2.c.
>
> > void gpmc_cs_write_reg(int cs, int idx, u32 val)
> > {
> > void __iomem *reg_addr;
> >
> > - reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx;
> > + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) +
> idx;
> > __raw_writel(val, reg_addr);
> > }
> >
> > @@ -120,7 +136,7 @@ u32 gpmc_cs_read_reg(int cs, int idx)
> > {
> > void __iomem *reg_addr;
> >
> > - reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx;
> > + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) +
> idx;
> > return __raw_readl(reg_addr);
> > }
> >
> > @@ -419,6 +435,96 @@ void gpmc_cs_free(int cs)
> > EXPORT_SYMBOL(gpmc_cs_free);
> >
> > /**
> > + * gpmc_hwcontrol - hardware specific access (read/ write) to control
> > + * @write: need 1 for configure; 0 for reading the complete register
> > + * @cs: chip select number
> > + * @cmd: Command type
> > + * @wval: value/information to write
> > + * @rval: pointer to get the value back
> > + */
> > +int gpmc_hwcontrol(int write, int cs, int cmd, int wval, int *rval)
> > +{
> > + u32 reg = 0;
> > + u32 regval = 0;
> > +
> > + switch (cmd) {
> > +
> > + case GPMC_GET_SET_STATUS:
> > + reg = GPMC_STATUS;
> > + if (write)
> > + gpmc_write_reg(GPMC_STATUS, regval);
> > + break;
> > +
> > + case GPMC_GET_SET_IRQ_STATUS:
> > + reg = GPMC_IRQSTATUS;
> > + if (write)
> > + gpmc_write_reg(GPMC_IRQSTATUS, regval);
> > + break;
> > +
> > + case GPMC_GET_PREF_STATUS:
> > + reg = GPMC_PREFETCH_STATUS;
> > + break;
> > +
> > + case GPMC_CONFIG_WP:
> > + reg = GPMC_CONFIG;
> > + regval = gpmc_read_reg(GPMC_CONFIG);
> > + if (wval)
> > + regval &= ~GPMC_CONFIG_WRITEPROTECT; /* WP is ON
> */
> > + else
> > + regval |= GPMC_CONFIG_WRITEPROTECT; /* WP is
> OFF */
> > + gpmc_write_reg(reg, regval);
> > + break;
> > +
> > + case GPMC_CONFIG_RDY_BSY:
> > + #define WR_RD_PIN_MONITORING 0x00600000
> > + regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
> > + regval |= WR_RD_PIN_MONITORING;
> > + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
> > + break;
> > +
> > + case GPMC_CONFIG_DEV_SIZE:
> > + regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
> > + regval |= GPMC_CONFIG1_DEVICESIZE(wval);
> > + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
> > + break;
> > +
> > + case GPMC_CONFIG_DEV_TYPE:
> > + regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
> > + regval |= GPMC_CONFIG1_DEVICETYPE(wval);
> > + if (wval == GPMC_DEVICETYPE_NOR)
> > + regval |= GPMC_CONFIG1_MUXADDDATA;
> > + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
> > + break;
> > +
> > + case GPMC_NAND_COMMAND:
> > + gpmc_cs_write_byte(cs, GPMC_CS_NAND_COMMAND, wval);
> > + break;
> > +
> > + case GPMC_NAND_ADDRESS:
> > + gpmc_cs_write_byte(cs, GPMC_CS_NAND_ADDRESS, wval);
> > + break;
> > +
> > + case GPMC_NAND_DATA:
> > + if (write)
> > + gpmc_cs_write_byte(cs, GPMC_CS_NAND_DATA, wval);
> > + else
> > + *rval = gpmc_cs_read_byte(cs,
> GPMC_CS_NAND_DATA);
> > + break;
> > +
> > + default:
> > + dump_stack();
> > + printk(KERN_ERR "not supported\n");
> > + return -1;
> > + }
> > +
> > + if (!write && reg)
> > + *rval = gpmc_read_reg(reg);
> > +
> > + return 0;
> > +}
> > +EXPORT_SYMBOL(gpmc_hwcontrol);
> > +
> > +/**
> > * gpmc_prefetch_enable - configures and starts prefetch transfer
> > * @cs: nand cs (chip select) number
> > * @dma_mode: dma mode enable (1) or disable (0)
> > @@ -466,15 +572,6 @@ void gpmc_prefetch_reset(void)
> > }
> > EXPORT_SYMBOL(gpmc_prefetch_reset);
> >
> > -/**
> > - * gpmc_prefetch_status - reads prefetch status of engine
> > - */
> > -int gpmc_prefetch_status(void)
> > -{
> > - return gpmc_read_reg(GPMC_PREFETCH_STATUS);
> > -}
> > -EXPORT_SYMBOL(gpmc_prefetch_status);
> > -
> > static void __init gpmc_mem_init(void)
> > {
> > int cs;
> > @@ -615,3 +712,86 @@ void omap3_gpmc_restore_context(void)
> > }
> > }
> > #endif /* CONFIG_ARCH_OMAP3 */
> > +
> > +/**
> > + * gmpc_ecc_init - Initialize the HW ECC for NAND flash in GPMC
> controller
> > + * @cs: Chip select number
> > + * @ecc_size: bytes for which ECC will be generated
> > + */
> > +void gpmc_ecc_init(int cs, int ecc_size)
> > +{
> > + unsigned int val = 0x0;
> > +
> > + /* Read from ECC Control Register */
> > + val = gpmc_read_reg(GPMC_ECC_CONTROL);
> > +
> > + /* Clear all ECC | Enable Reg1 */
> > + val = ((0x00000001<<8) | 0x00000001);
> > + gpmc_write_reg(GPMC_ECC_CONTROL, val);
> > +
> > + /* Read from ECC Size Config Register */
> > + val = gpmc_read_reg(GPMC_ECC_SIZE_CONFIG);
> > + /* ECCSIZE1=512 | Select eccResultsize[0-3] */
> > + val = ((((ecc_size >> 1) - 1) << 22) | (0x0000000F));
> > + gpmc_write_reg(GPMC_ECC_SIZE_CONFIG, val);
> > +}
> > +
> > +/**
> > + * gpmc_calcuate_ecc - Generate non-inverted ECC bytes.
> > + * @cs: Chip select number
> > + * @dat: The pointer to data on which ecc is computed
> > + * @ecc_code: The ecc_code buffer
> > + *
> > + * Using noninverted ECC can be considered ugly since writing a blank
> > + * page ie. padding will clear the ECC bytes. This is no problem as
> long
> > + * nobody is trying to write data on the seemingly unused page. Reading
> > + * an erased page will produce an ECC mismatch between generated and
> read
> > + * ECC bytes that has to be dealt with separately.
> > + */
> > +int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code)
> > +{
> > + unsigned int val = 0x0;
> > +
> > + /* Start Reading from HW ECC1_Result = 0x200 */
> > + val = gpmc_read_reg(GPMC_ECC1_RESULT);
> > + *ecc_code++ = val; /* P128e, ..., P1e */
> > + *ecc_code++ = val >> 16; /* P128o, ..., P1o */
> > + /* P2048o, P1024o, P512o, P256o, P2048e, P1024e, P512e, P256e */
> > + *ecc_code++ = ((val >> 8) & 0x0f) | ((val >> 20) & 0xf0);
> > +
> > + return 0;
> > +}
> > +
> > +/**
> > + * gpmc_enable_hwecc - This function enables the hardware ecc
> functionality
> > + * @cs: Chip select number
> > + * @mode: Read/Write mode
> > + * @dev_width: device bus width
> > + */
> > +void gpmc_enable_hwecc(int cs, int mode, int dev_width)
> > +{
> > + unsigned int val = gpmc_read_reg(GPMC_ECC_CONFIG);
> > +
> > + switch (mode) {
> > + case GPMC_ECC_READ:
> > + gpmc_write_reg(GPMC_ECC_CONTROL, 0x101);
> > + /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */
> > + val = (dev_width << 7) | (cs << 1) | (0x1);
> > + break;
> > + case GPMC_ECC_READSYN:
> > + gpmc_write_reg(GPMC_ECC_CONTROL, 0x100);
> > + /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */
> > + val = (dev_width << 7) | (cs << 1) | (0x1);
> > + break;
> > + case GPMC_ECC_WRITE:
> > + gpmc_write_reg(GPMC_ECC_CONTROL, 0x101);
> > + /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */
> > + val = (dev_width << 7) | (cs << 1) | (0x1);
> > + break;
> > + default:
> > + printk(KERN_INFO "Error: Unrecognized Mode[%d]!\n",
> mode);
> > + break;
> > + }
> > +
> > + gpmc_write_reg(GPMC_ECC_CONFIG, val);
> > +}
> > diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-
> omap/include/plat/gpmc.h
> > index 145838a..56e1407
> > --- a/arch/arm/plat-omap/include/plat/gpmc.h
> > +++ b/arch/arm/plat-omap/include/plat/gpmc.h
> > @@ -25,10 +25,22 @@
> > #define GPMC_CS_NAND_ADDRESS 0x20
> > #define GPMC_CS_NAND_DATA 0x24
> >
> > -#define GPMC_CONFIG 0x50
> > -#define GPMC_STATUS 0x54
> > -#define GPMC_CS0_BASE 0x60
> > -#define GPMC_CS_SIZE 0x30
> > +/* Control Commands */
> > +#define GPMC_GET_SET_STATUS 0x00000001
> > +#define GPMC_CONFIG_WP 0x00000002
> > +#define GPMC_CONFIG_RDY_BSY 0x00000003
> > +#define GPMC_CONFIG_DEV_SIZE 0x00000004
> > +#define GPMC_CONFIG_DEV_TYPE 0x00000005
> > +#define GPMC_NAND_COMMAND 0x00000006
> > +#define GPMC_NAND_ADDRESS 0x00000007
> > +#define GPMC_NAND_DATA 0x00000008
> > +#define GPMC_GET_PREF_STATUS 0x00000009
> > +#define GPMC_GET_SET_IRQ_STATUS 0x0000000a
> > +
> > +/* ECC commands */
> > +#define GPMC_ECC_READ 0 /* Reset Hardware ECC for read */
> > +#define GPMC_ECC_WRITE 1 /* Reset Hardware ECC for write */
> > +#define GPMC_ECC_READSYN 2 /* Reset before syndrom is read back
> */
> >
> > #define GPMC_CONFIG1_WRAPBURST_SUPP (1 << 31)
> > #define GPMC_CONFIG1_READMULTIPLE_SUPP (1 << 30)
> > @@ -44,10 +56,7 @@
> > #define GPMC_CONFIG1_WAIT_MON_IIME(val) ((val & 3) << 18)
> > #define GPMC_CONFIG1_WAIT_PIN_SEL(val) ((val & 3) << 16)
> > #define GPMC_CONFIG1_DEVICESIZE(val) ((val & 3) << 12)
> > -#define GPMC_CONFIG1_DEVICESIZE_16 GPMC_CONFIG1_DEVICESIZE(1)
> > #define GPMC_CONFIG1_DEVICETYPE(val) ((val & 3) << 10)
> > -#define GPMC_CONFIG1_DEVICETYPE_NOR GPMC_CONFIG1_DEVICETYPE(0)
> > -#define GPMC_CONFIG1_DEVICETYPE_NAND GPMC_CONFIG1_DEVICETYPE(2)
> > #define GPMC_CONFIG1_MUXADDDATA (1 << 9)
> > #define GPMC_CONFIG1_TIME_PARA_GRAN (1 << 4)
> > #define GPMC_CONFIG1_FCLK_DIV(val) (val & 3)
> > @@ -56,6 +65,12 @@
> > #define GPMC_CONFIG1_FCLK_DIV4 (GPMC_CONFIG1_FCLK_DIV(3))
> > #define GPMC_CONFIG7_CSVALID (1 << 6)
> >
> > +#define GPMC_DEVICETYPE_NOR 0
> > +#define GPMC_DEVICETYPE_NAND 2
> > +#define GPMC_CONFIG_WRITEPROTECT 0x00000010
> > +#define GPMC_CONFIG1_DEVICESIZE_16 GPMC_CONFIG1_DEVICESIZE(1)
> > +
> > +
> > /*
> > * Note that all values in this struct are in nanoseconds, while
> > * the register values are in gpmc_fck cycles.
> > @@ -109,9 +124,14 @@ extern int gpmc_cs_reserved(int cs);
> > extern int gpmc_prefetch_enable(int cs, int dma_mode,
> > unsigned int u32_count, int
> is_write);
> > extern void gpmc_prefetch_reset(void);
> > -extern int gpmc_prefetch_status(void);
> > extern void omap3_gpmc_save_context(void);
> > extern void omap3_gpmc_restore_context(void);
> > extern void gpmc_init(void);
> > +extern int gpmc_hwcontrol(int write, int cs, int cmd, int wval, int
> *rval);
> > +
> > +void gpmc_ecc_init(int cs, int ecc_size);
> > +void gpmc_enable_hwecc(int cs, int mode, int dev_width);
> > +int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code);
> > +
> >
> > #endif
> > diff --git a/arch/arm/plat-omap/include/plat/nand.h b/arch/arm/plat-
> omap/include/plat/nand.h
> > index f8efd54..6562cd0
> > --- a/arch/arm/plat-omap/include/plat/nand.h
> > +++ b/arch/arm/plat-omap/include/plat/nand.h
> > @@ -21,13 +21,11 @@ struct omap_nand_platform_data {
> > int (*dev_ready)(struct
> omap_nand_platform_data *);
> > int dma_channel;
> > unsigned long phys_base;
> > - void __iomem *gpmc_cs_baseaddr;
> > - void __iomem *gpmc_baseaddr;
> > int devsize;
> > };
> >
> > -/* size (4 KiB) for IO mapping */
> > -#define NAND_IO_SIZE SZ_4K
> > +/* minimum size for IO mapping */
> > +#define NAND_IO_SIZE 4
> >
> > #if defined(CONFIG_MTD_NAND_OMAP2) ||
> defined(CONFIG_MTD_NAND_OMAP2_MODULE)
> > extern int gpmc_nand_init(struct omap_nand_platform_data *d);
> > diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
> > index 7545568..1858c42
> > --- a/drivers/mtd/nand/omap2.c
> > +++ b/drivers/mtd/nand/omap2.c
> > @@ -23,12 +23,6 @@
> > #include <plat/gpmc.h>
> > #include <plat/nand.h>
> >
> > -#define GPMC_IRQ_STATUS 0x18
> > -#define GPMC_ECC_CONFIG 0x1F4
> > -#define GPMC_ECC_CONTROL 0x1F8
> > -#define GPMC_ECC_SIZE_CONFIG 0x1FC
> > -#define GPMC_ECC1_RESULT 0x200
> > -
> > #define DRIVER_NAME "omap2-nand"
> >
> > #define NAND_WP_OFF 0
> > @@ -37,6 +31,7 @@
> > #define GPMC_BUF_FULL 0x00000001
> > #define GPMC_BUF_EMPTY 0x00000000
> >
> > +#ifdef CONFIG_MTD_NAND_OMAP_HWECC
> > #define NAND_Ecc_P1e (1 << 0)
> > #define NAND_Ecc_P2e (1 << 1)
> > #define NAND_Ecc_P4e (1 << 2)
> > @@ -103,6 +98,7 @@
> >
> > #define P4e_s(a) (TF(a & NAND_Ecc_P4e) << 0)
> > #define P4o_s(a) (TF(a & NAND_Ecc_P4o) << 1)
> > +#endif /* CONFIG_MTD_NAND_OMAP_HWECC */
>
> Why this ifdef macro?
>
> >
> > #ifdef CONFIG_MTD_PARTITIONS
> > static const char *part_probes[] = { "cmdlinepart", NULL };
> > @@ -139,34 +135,11 @@ struct omap_nand_info {
> >
> > int gpmc_cs;
> > unsigned long phys_base;
> > - void __iomem *gpmc_cs_baseaddr;
> > - void __iomem *gpmc_baseaddr;
> > - void __iomem *nand_pref_fifo_add;
> > struct completion comp;
> > int dma_ch;
> > };
> >
> > /**
> > - * omap_nand_wp - This function enable or disable the Write Protect
> feature
> > - * @mtd: MTD device structure
> > - * @mode: WP ON/OFF
> > - */
> > -static void omap_nand_wp(struct mtd_info *mtd, int mode)
> > -{
> > - struct omap_nand_info *info = container_of(mtd,
> > - struct omap_nand_info,
> mtd);
> > -
> > - unsigned long config = __raw_readl(info->gpmc_baseaddr +
> GPMC_CONFIG);
> > -
> > - if (mode)
> > - config &= ~(NAND_WP_BIT); /* WP is ON */
> > - else
> > - config |= (NAND_WP_BIT); /* WP is OFF */
> > -
> > - __raw_writel(config, (info->gpmc_baseaddr + GPMC_CONFIG));
> > -}
> > -
> > -/**
> > * omap_hwcontrol - hardware specific access to control-lines
> > * @mtd: MTD device structure
> > * @cmd: command to device
> > @@ -181,31 +154,20 @@ static void omap_hwcontrol(struct mtd_info *mtd,
> int cmd, unsigned int ctrl)
> > {
> > struct omap_nand_info *info = container_of(mtd,
> > struct omap_nand_info, mtd);
> > - switch (ctrl) {
> > - case NAND_CTRL_CHANGE | NAND_CTRL_CLE:
> > - info->nand.IO_ADDR_W = info->gpmc_cs_baseaddr +
> > - GPMC_CS_NAND_COMMAND;
> > - info->nand.IO_ADDR_R = info->gpmc_cs_baseaddr +
> > - GPMC_CS_NAND_DATA;
> > - break;
> > -
> > - case NAND_CTRL_CHANGE | NAND_CTRL_ALE:
> > - info->nand.IO_ADDR_W = info->gpmc_cs_baseaddr +
> > - GPMC_CS_NAND_ADDRESS;
> > - info->nand.IO_ADDR_R = info->gpmc_cs_baseaddr +
> > - GPMC_CS_NAND_DATA;
> > - break;
> > -
> > - case NAND_CTRL_CHANGE | NAND_NCE:
> > - info->nand.IO_ADDR_W = info->gpmc_cs_baseaddr +
> > - GPMC_CS_NAND_DATA;
> > - info->nand.IO_ADDR_R = info->gpmc_cs_baseaddr +
> > - GPMC_CS_NAND_DATA;
> > - break;
> > - }
> >
> > - if (cmd != NAND_CMD_NONE)
> > - __raw_writeb(cmd, info->nand.IO_ADDR_W);
> > + if (cmd != NAND_CMD_NONE) {
> > + if (ctrl & NAND_CLE) {
> > + gpmc_hwcontrol(1, info->gpmc_cs,
> > + GPMC_NAND_COMMAND, cmd, NULL);
> > +
> > + } else if (ctrl & NAND_ALE) {
> > + gpmc_hwcontrol(1, info->gpmc_cs,
> > + GPMC_NAND_ADDRESS, cmd, NULL);
> > +
> > + } else /* NAND_NCE */
> > + gpmc_hwcontrol(1, info->gpmc_cs,
> > + GPMC_NAND_DATA, cmd, NULL);
> > + }
> > }
> >
> > /**
> > @@ -229,14 +191,15 @@ static void omap_read_buf8(struct mtd_info *mtd,
> u_char *buf, int len)
> > */
> > static void omap_write_buf8(struct mtd_info *mtd, const u_char *buf,
> int len)
> > {
> > - struct omap_nand_info *info = container_of(mtd,
> > - struct omap_nand_info,
> mtd);
> > + u32 status;
> > + struct nand_chip *nand = mtd->priv;
> > u_char *p = (u_char *)buf;
> >
> > while (len--) {
> > - iowrite8(*p++, info->nand.IO_ADDR_W);
> > - while (GPMC_BUF_EMPTY == (readl(info->gpmc_baseaddr +
> > - GPMC_STATUS) &
> GPMC_BUF_FULL));
> > + iowrite8(*p++, nand->IO_ADDR_W);
> > + gpmc_hwcontrol(0, 0, GPMC_GET_SET_STATUS, 0, &status);
> If I am not mistaking, 2nd argument is 'cs', correct? And then, why
> are you hard coding this?
> Different boards will have NAND chip present at different 'cs'.
> Please have a look at uses of 'gpmc_hwcontrol' elsewhere as well for this.
[Ghorai] I agree.
>
> Again, say, you got '(status & GPMC_BUF_FULL) != GPMC_BUF_EMPTY', then:
>
> > + while (GPMC_BUF_EMPTY == (status & GPMC_BUF_FULL))
> > + ;
>
> You got in an infinite loop here?
[Ghorai] if you see carefully this is same as existing code. Let me check if any better solution.
>
> > }
> > }
> >
> > @@ -261,18 +224,17 @@ static void omap_read_buf16(struct mtd_info *mtd,
> u_char *buf, int len)
> > */
> > static void omap_write_buf16(struct mtd_info *mtd, const u_char * buf,
> int len)
> > {
> > - struct omap_nand_info *info = container_of(mtd,
> > - struct omap_nand_info,
> mtd);
> > + u32 status;
> > + struct nand_chip *nand = mtd->priv;
> > u16 *p = (u16 *) buf;
> >
> > /* FIXME try bursts of writesw() or DMA ... */
> > len >>= 1;
> >
> > while (len--) {
> > - iowrite16(*p++, info->nand.IO_ADDR_W);
> > -
> > - while (GPMC_BUF_EMPTY == (readl(info->gpmc_baseaddr +
> > - GPMC_STATUS) &
> GPMC_BUF_FULL))
> > + iowrite16(*p++, nand->IO_ADDR_W);
> > + gpmc_hwcontrol(0, 0, GPMC_GET_SET_STATUS, 0, &status);
> > + while (GPMC_BUF_EMPTY == (status & GPMC_BUF_FULL))
>
> same as above.
[Ghorai] if you see carefully this is same as existing code. Let me check if any better solution.
>
>
> --
> Regards,
> Vimal Singh
^ permalink raw reply [flat|nested] 102+ messages in thread
* RE: [PATCH v2 1/2] omap3 nand: cleanup for not to use GPMC virtual address
2010-05-14 23:58 ` Tony Lindgren
@ 2010-05-17 5:48 ` Ghorai, Sukumar
0 siblings, 0 replies; 102+ messages in thread
From: Ghorai, Sukumar @ 2010-05-17 5:48 UTC (permalink / raw)
To: Tony Lindgren
Cc: linux-omap@vger.kernel.org, linux-mtd@lists.infradead.org,
sakoman@gmail.com, mike@compulab.co.il,
Artem.Bityutskiy@nokia.com
Tony,
> -----Original Message-----
> From: Tony Lindgren [mailto:tony@atomide.com]
> Sent: 2010-05-15 05:29
> To: Ghorai, Sukumar
> Cc: linux-omap@vger.kernel.org; linux-mtd@lists.infradead.org;
> sakoman@gmail.com; mike@compulab.co.il; Artem.Bityutskiy@nokia.com
> Subject: Re: [PATCH v2 1/2] omap3 nand: cleanup for not to use GPMC
> virtual address
>
> Few more comments below.
>
> * Sukumar Ghorai <s-ghorai@ti.com> [100514 08:18]:
> > +
> > +/**
> > + * gmpc_ecc_init - Initialize the HW ECC for NAND flash in GPMC
> controller
> > + * @cs: Chip select number
> > + * @ecc_size: bytes for which ECC will be generated
> > + */
> > +void gpmc_ecc_init(int cs, int ecc_size)
> > +{
> > + unsigned int val = 0x0;
> > +
> > + /* Read from ECC Control Register */
> > + val = gpmc_read_reg(GPMC_ECC_CONTROL);
> > +
> > + /* Clear all ECC | Enable Reg1 */
> > + val = ((0x00000001<<8) | 0x00000001);
> > + gpmc_write_reg(GPMC_ECC_CONTROL, val);
> > +
> > + /* Read from ECC Size Config Register */
> > + val = gpmc_read_reg(GPMC_ECC_SIZE_CONFIG);
> > + /* ECCSIZE1=512 | Select eccResultsize[0-3] */
> > + val = ((((ecc_size >> 1) - 1) << 22) | (0x0000000F));
> > + gpmc_write_reg(GPMC_ECC_SIZE_CONFIG, val);
> > +}
>
> There should be some locking as only one chipselect can use
> the ECC or prefetch engine at a time. If you have NAND in
> two chipselects, bad things would happen..
>
> Maybe something like:
>
> int gpmc_ecc_request(int cs);
> void gpmc_ecc_free(int cs);
> int gpmc_prefetch_request(int cs);
> void gpmc_prefetch_free(int cs);
>
> Other than that, looks like a good clean-up so we can easily
> add the platform init code for all the board files.
[Ghorai] agreed.. and -
1). Adding one flag/variable for prefetch enable/reset request
2). Adding another flag/variable for ecc int/reset request
Regards,
Ghorai
>
> Regards,
>
> Tony
^ permalink raw reply [flat|nested] 102+ messages in thread
* Re: [PATCH v2 1/2] omap3 nand: cleanup for not to use GPMC virtual address
2010-05-17 4:22 ` Ghorai, Sukumar
@ 2010-05-17 14:26 ` Vimal Singh
2010-05-17 14:34 ` Ghorai, Sukumar
0 siblings, 1 reply; 102+ messages in thread
From: Vimal Singh @ 2010-05-17 14:26 UTC (permalink / raw)
To: Ghorai, Sukumar
Cc: linux-omap@vger.kernel.org, Artem.Bityutskiy@nokia.com,
tony@atomide.com, sakoman@gmail.com,
linux-mtd@lists.infradead.org
On Mon, May 17, 2010 at 9:52 AM, Ghorai, Sukumar <s-ghorai@ti.com> wrote:
[...]
>> > @@ -108,11 +108,27 @@ static u32 gpmc_read_reg(int idx)
>> > return __raw_readl(gpmc_base + idx);
>> > }
>> >
>> > +static void gpmc_cs_write_byte(int cs, int idx, u8 val)
>> > +{
>> > + void __iomem *reg_addr;
>> > +
>> > + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) +
>> idx;
>> > + __raw_writeb(val, reg_addr);
>> > +}
>> > +
>> > +static u8 gpmc_cs_read_byte(int cs, int idx)
>> > +{
>> > + void __iomem *reg_addr;
>> > +
>> > + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) +
>> idx;
>> > + return __raw_readb(reg_addr);
>> > +}
>> > +
>>
>> I do not think we need these functions.
> [Ghorai] This is used in gpmc_hwcontrol() and to get the nand status from omap2.c.
Yes, I can see that. But I think you should read complete register
(32-bits) and the manipulate them accordingly.
>
[...]
>> > @@ -229,14 +191,15 @@ static void omap_read_buf8(struct mtd_info *mtd,
>> u_char *buf, int len)
>> > */
>> > static void omap_write_buf8(struct mtd_info *mtd, const u_char *buf,
>> int len)
>> > {
>> > - struct omap_nand_info *info = container_of(mtd,
>> > - struct omap_nand_info,
>> mtd);
>> > + u32 status;
>> > + struct nand_chip *nand = mtd->priv;
>> > u_char *p = (u_char *)buf;
>> >
>> > while (len--) {
>> > - iowrite8(*p++, info->nand.IO_ADDR_W);
>> > - while (GPMC_BUF_EMPTY == (readl(info->gpmc_baseaddr +
>> > - GPMC_STATUS) &
>> GPMC_BUF_FULL));
>> > + iowrite8(*p++, nand->IO_ADDR_W);
>> > + gpmc_hwcontrol(0, 0, GPMC_GET_SET_STATUS, 0, &status);
>> If I am not mistaking, 2nd argument is 'cs', correct? And then, why
>> are you hard coding this?
>> Different boards will have NAND chip present at different 'cs'.
>> Please have a look at uses of 'gpmc_hwcontrol' elsewhere as well for this.
> [Ghorai] I agree.
>>
>> Again, say, you got '(status & GPMC_BUF_FULL) != GPMC_BUF_EMPTY', then:
>>
>> > + while (GPMC_BUF_EMPTY == (status & GPMC_BUF_FULL))
>> > + ;
>>
>> You got in an infinite loop here?
> [Ghorai] if you see carefully this is same as existing code. Let me check if any better solution.
No. Look carefully. In previous code 'gpmc status' was being read in
each loop, while in your code you read it once and then you never look
for updated value.
That's why your code is going into infinite loop
--
Regards,
Vimal Singh
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 102+ messages in thread
* RE: [PATCH v2 1/2] omap3 nand: cleanup for not to use GPMC virtual address
2010-05-17 14:26 ` Vimal Singh
@ 2010-05-17 14:34 ` Ghorai, Sukumar
0 siblings, 0 replies; 102+ messages in thread
From: Ghorai, Sukumar @ 2010-05-17 14:34 UTC (permalink / raw)
To: Vimal Singh
Cc: linux-omap@vger.kernel.org, Artem.Bityutskiy@nokia.com,
tony@atomide.com, sakoman@gmail.com,
linux-mtd@lists.infradead.org
> -----Original Message-----
> From: Vimal Singh [mailto:vimal.newwork@gmail.com]
> Sent: 2010-05-17 19:57
> To: Ghorai, Sukumar
> Cc: linux-omap@vger.kernel.org; Artem.Bityutskiy@nokia.com;
> tony@atomide.com; sakoman@gmail.com; linux-mtd@lists.infradead.org
> Subject: Re: [PATCH v2 1/2] omap3 nand: cleanup for not to use GPMC
> virtual address
>
> On Mon, May 17, 2010 at 9:52 AM, Ghorai, Sukumar <s-ghorai@ti.com> wrote:
> [...]
> >> > @@ -108,11 +108,27 @@ static u32 gpmc_read_reg(int idx)
> >> > return __raw_readl(gpmc_base + idx);
> >> > }
> >> >
> >> > +static void gpmc_cs_write_byte(int cs, int idx, u8 val)
> >> > +{
> >> > + void __iomem *reg_addr;
> >> > +
> >> > + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) +
> >> idx;
> >> > + __raw_writeb(val, reg_addr);
> >> > +}
> >> > +
> >> > +static u8 gpmc_cs_read_byte(int cs, int idx)
> >> > +{
> >> > + void __iomem *reg_addr;
> >> > +
> >> > + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) +
> >> idx;
> >> > + return __raw_readb(reg_addr);
> >> > +}
> >> > +
> >>
> >> I do not think we need these functions.
> > [Ghorai] This is used in gpmc_hwcontrol() and to get the nand status
> from omap2.c.
>
> Yes, I can see that. But I think you should read complete register
> (32-bits) and the manipulate them accordingly.
>
> >
> [...]
> >> > @@ -229,14 +191,15 @@ static void omap_read_buf8(struct mtd_info
> *mtd,
> >> u_char *buf, int len)
> >> > */
> >> > static void omap_write_buf8(struct mtd_info *mtd, const u_char *buf,
> >> int len)
> >> > {
> >> > - struct omap_nand_info *info = container_of(mtd,
> >> > - struct
> omap_nand_info,
> >> mtd);
> >> > + u32 status;
> >> > + struct nand_chip *nand = mtd->priv;
> >> > u_char *p = (u_char *)buf;
> >> >
> >> > while (len--) {
> >> > - iowrite8(*p++, info->nand.IO_ADDR_W);
> >> > - while (GPMC_BUF_EMPTY == (readl(info->gpmc_baseaddr +
> >> > - GPMC_STATUS) &
> >> GPMC_BUF_FULL));
> >> > + iowrite8(*p++, nand->IO_ADDR_W);
> >> > + gpmc_hwcontrol(0, 0, GPMC_GET_SET_STATUS, 0,
> &status);
> >> If I am not mistaking, 2nd argument is 'cs', correct? And then, why
> >> are you hard coding this?
> >> Different boards will have NAND chip present at different 'cs'.
> >> Please have a look at uses of 'gpmc_hwcontrol' elsewhere as well for
> this.
> > [Ghorai] I agree.
> >>
> >> Again, say, you got '(status & GPMC_BUF_FULL) != GPMC_BUF_EMPTY', then:
> >>
> >> > + while (GPMC_BUF_EMPTY == (status & GPMC_BUF_FULL))
> >> > + ;
> >>
> >> You got in an infinite loop here?
> > [Ghorai] if you see carefully this is same as existing code. Let me
> check if any better solution.
>
> No. Look carefully. In previous code 'gpmc status' was being read in
> each loop, while in your code you read it once and then you never look
> for updated value.
> That's why your code is going into infinite loop
[Ghorai] ok. thanks
>
>
> --
> Regards,
> Vimal Singh
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 102+ messages in thread
* [PATCH v3 0/3] omap3 nand: cleanup exiting platform related code
[not found] <Sukumar Ghorai <s-ghorai@ti.com>
` (11 preceding siblings ...)
2010-05-14 15:23 ` [PATCH v2 0/2] " Sukumar Ghorai
@ 2010-05-18 11:16 ` Sukumar Ghorai
2010-05-18 11:16 ` [PATCH v3 1/3] omap3 gpmc: functionality enhancement Sukumar Ghorai
2010-05-27 13:24 ` [PATCH v4 0/3] omap3 nand: cleanup exiting platform related code Sukumar Ghorai
` (2 subsequent siblings)
15 siblings, 1 reply; 102+ messages in thread
From: Sukumar Ghorai @ 2010-05-18 11:16 UTC (permalink / raw)
To: linux-omap
Cc: linux-mtd, tony, sakoman, mike, Artem.Bityutskiy, Sukumar Ghorai
The following set of patches applies on top of for-next branch.
http://git.kernel.org/?p=linux/kernel/git/tmlind/linux-omap-2.6.git
Patches verified on: omap3430-SDP, omap3630-sdp, zoom3 and beagle board
And these are the patches required to address the following input -
1. The NAND driver needs to stop tinkering with the GPMC registers
The omap General Purpose Memory Controller (GPMC) registers are omap
specific, and not driver specific. Tinkering with these registers can
cause issues with the other devices on the GPMC.
2. Passing hardcoded GPMC_CS0_BASE needs to go from the board files
Passing hardcoded GPMC virtual addressess is sure way to mess up things.
This should all become unnecessary once the NAND drivers stops messing
with the GPMC registers directly.
v2: http://www.mail-archive.com/linux-omap@vger.kernel.org/msg28467.html
Few functionality was missing like - There should be some locking
as only one chipselect can use the ECC or prefetch engine at a time.
If you have NAND in two chipselects, bad things would happen.
v1: http://www.mail-archive.com/linux-omap@vger.kernel.org/msg28164.html
Additionally, it was needed to implement more functions for the
platform init code to use.
Sukumar Ghorai (3):
omap3 gpmc: functionality enhancement
omap3 nand: cleanup virtual address usages
omap3 nand: fix issue in board file to detect nand
arch/arm/mach-omap2/board-cm-t35.c | 20 +---
arch/arm/mach-omap2/board-devkit8000.c | 25 +---
arch/arm/mach-omap2/board-omap3beagle.c | 24 +---
arch/arm/mach-omap2/board-omap3touchbook.c | 25 +---
arch/arm/mach-omap2/board-overo.c | 24 +---
arch/arm/mach-omap2/gpmc-nand.c | 39 ++----
arch/arm/mach-omap2/gpmc.c | 9 -
arch/arm/plat-omap/include/plat/gpmc.h | 7 +-
arch/arm/plat-omap/include/plat/nand.h | 6 +-
drivers/mtd/nand/omap2.c | 242 +++++++++-------------------
10 files changed, 93 insertions(+), 328 deletions(-)
^ permalink raw reply [flat|nested] 102+ messages in thread
* [PATCH v3 1/3] omap3 gpmc: functionality enhancement
2010-05-18 11:16 ` [PATCH v3 0/3] omap3 nand: cleanup exiting platform related code Sukumar Ghorai
@ 2010-05-18 11:16 ` Sukumar Ghorai
2010-05-18 11:16 ` [PATCH v3 2/3] omap3 nand: cleanup virtual address usages Sukumar Ghorai
2010-05-19 14:46 ` [PATCH v3 1/3] omap3 gpmc: functionality enhancement Vimal Singh
0 siblings, 2 replies; 102+ messages in thread
From: Sukumar Ghorai @ 2010-05-18 11:16 UTC (permalink / raw)
To: linux-omap
Cc: linux-mtd, tony, sakoman, mike, Artem.Bityutskiy, Sukumar Ghorai
few functions added in gpmc module and to be used by other drivers like NAND.
E.g.: - ioctl function
- ecc functions
Signed-off-by: Sukumar Ghorai <s-ghorai@ti.com>
---
arch/arm/mach-omap2/gpmc.c | 246 +++++++++++++++++++++++++++++++-
arch/arm/plat-omap/include/plat/gpmc.h | 35 ++++-
drivers/mtd/nand/omap2.c | 4 +-
3 files changed, 274 insertions(+), 11 deletions(-)
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index 5bc3ca0..7e6d821
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -46,8 +46,9 @@
#define GPMC_ECC_CONFIG 0x1f4
#define GPMC_ECC_CONTROL 0x1f8
#define GPMC_ECC_SIZE_CONFIG 0x1fc
+#define GPMC_ECC1_RESULT 0x200
-#define GPMC_CS0 0x60
+#define GPMC_CS0_BASE 0x60
#define GPMC_CS_SIZE 0x30
#define GPMC_MEM_START 0x00000000
@@ -92,7 +93,9 @@ struct omap3_gpmc_regs {
static struct resource gpmc_mem_root;
static struct resource gpmc_cs_mem[GPMC_CS_NUM];
static DEFINE_SPINLOCK(gpmc_mem_lock);
-static unsigned gpmc_cs_map;
+static unsigned int gpmc_cs_map; /* flag for cs which are initialized */
+static int gpmc_pref_used = -EINVAL; /* cs using prefetch engine */
+static int gpmc_ecc_used = -EINVAL; /* cs using ecc engine */
static void __iomem *gpmc_base;
@@ -108,11 +111,27 @@ static u32 gpmc_read_reg(int idx)
return __raw_readl(gpmc_base + idx);
}
+static void gpmc_cs_write_byte(int cs, int idx, u8 val)
+{
+ void __iomem *reg_addr;
+
+ reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx;
+ __raw_writeb(val, reg_addr);
+}
+
+static u8 gpmc_cs_read_byte(int cs, int idx)
+{
+ void __iomem *reg_addr;
+
+ reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx;
+ return __raw_readb(reg_addr);
+}
+
void gpmc_cs_write_reg(int cs, int idx, u32 val)
{
void __iomem *reg_addr;
- reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx;
+ reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx;
__raw_writel(val, reg_addr);
}
@@ -120,7 +139,7 @@ u32 gpmc_cs_read_reg(int cs, int idx)
{
void __iomem *reg_addr;
- reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx;
+ reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx;
return __raw_readl(reg_addr);
}
@@ -419,8 +438,100 @@ void gpmc_cs_free(int cs)
EXPORT_SYMBOL(gpmc_cs_free);
/**
+ * gpmc_hwcontrol - hardware specific access (read/ write) control
+ * @cs: chip select number
+ * @cmd: command type
+ * @write: 1 for write; 0 for read
+ * @wval: value to write
+ * @rval: read pointer
+ */
+int gpmc_hwcontrol(int cs, int cmd, int write, int wval, int *rval)
+{
+ u32 regval = 0;
+
+ if (!write && !rval)
+ return -EINVAL;
+
+ switch (cmd) {
+ case GPMC_STATUS_BUFFER:
+ regval = gpmc_read_reg(GPMC_STATUS);
+ /* 1 : buffer is available to write */
+ *rval = regval & GPMC_STATUS_BUFF_EMPTY;
+ break;
+
+ case GPMC_GET_SET_IRQ_STATUS:
+ if (write)
+ gpmc_write_reg(GPMC_IRQSTATUS, wval);
+ else
+ *rval = gpmc_read_reg(GPMC_IRQSTATUS);
+ break;
+
+ case GPMC_PREFETCH_FIFO_CNT:
+ regval = gpmc_read_reg(GPMC_PREFETCH_STATUS);
+ *rval = GPMC_PREFETCH_STATUS_FIFO_CNT(regval);
+ break;
+
+ case GPMC_PREFETCH_COUNT:
+ regval = gpmc_read_reg(GPMC_PREFETCH_STATUS);
+ *rval = GPMC_PREFETCH_STATUS_COUNT(regval);
+ break;
+
+ case GPMC_CONFIG_WP:
+ regval = gpmc_read_reg(GPMC_CONFIG);
+ if (wval)
+ regval &= ~GPMC_CONFIG_WRITEPROTECT; /* WP is ON */
+ else
+ regval |= GPMC_CONFIG_WRITEPROTECT; /* WP is OFF */
+ gpmc_write_reg(GPMC_CONFIG, regval);
+ break;
+
+ case GPMC_CONFIG_RDY_BSY:
+ regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
+ regval |= WR_RD_PIN_MONITORING;
+ gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
+ break;
+
+ case GPMC_CONFIG_DEV_SIZE:
+ regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
+ regval |= GPMC_CONFIG1_DEVICESIZE(wval);
+ gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
+ break;
+
+ case GPMC_CONFIG_DEV_TYPE:
+ regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
+ regval |= GPMC_CONFIG1_DEVICETYPE(wval);
+ if (wval == GPMC_DEVICETYPE_NOR)
+ regval |= GPMC_CONFIG1_MUXADDDATA;
+ gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
+ break;
+
+ case GPMC_NAND_COMMAND:
+ gpmc_cs_write_byte(cs, GPMC_CS_NAND_COMMAND, wval);
+ break;
+
+ case GPMC_NAND_ADDRESS:
+ gpmc_cs_write_byte(cs, GPMC_CS_NAND_ADDRESS, wval);
+ break;
+
+ case GPMC_NAND_DATA:
+ if (write)
+ gpmc_cs_write_byte(cs, GPMC_CS_NAND_DATA, wval);
+ else
+ *rval = gpmc_cs_read_byte(cs, GPMC_CS_NAND_DATA);
+ break;
+
+ default:
+ printk(KERN_ERR "gpmc_hwcontrol: Not supported\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(gpmc_hwcontrol);
+
+/**
* gpmc_prefetch_enable - configures and starts prefetch transfer
- * @cs: nand cs (chip select) number
+ * @cs: cs (chip select) number
* @dma_mode: dma mode enable (1) or disable (0)
* @u32_count: number of bytes to be transferred
* @is_write: prefetch read(0) or write post(1) mode
@@ -430,6 +541,11 @@ int gpmc_prefetch_enable(int cs, int dma_mode,
{
uint32_t prefetch_config1;
+ if (gpmc_pref_used == -EINVAL)
+ gpmc_pref_used = cs;
+ else
+ return -EBUSY;
+
if (!(gpmc_read_reg(GPMC_PREFETCH_CONTROL))) {
/* Set the amount of bytes to be prefetched */
gpmc_write_reg(GPMC_PREFETCH_CONFIG2, u32_count);
@@ -456,13 +572,20 @@ EXPORT_SYMBOL(gpmc_prefetch_enable);
/**
* gpmc_prefetch_reset - disables and stops the prefetch engine
*/
-void gpmc_prefetch_reset(void)
+int gpmc_prefetch_reset(int cs)
{
+ if (gpmc_pref_used == cs)
+ gpmc_pref_used = -EINVAL;
+ else
+ return -EINVAL;
+
/* Stop the PFPW engine */
gpmc_write_reg(GPMC_PREFETCH_CONTROL, 0x0);
/* Reset/disable the PFPW engine */
gpmc_write_reg(GPMC_PREFETCH_CONFIG1, 0x0);
+
+ return 0;
}
EXPORT_SYMBOL(gpmc_prefetch_reset);
@@ -615,3 +738,114 @@ void omap3_gpmc_restore_context(void)
}
}
#endif /* CONFIG_ARCH_OMAP3 */
+
+/**
+ * gpmc_ecc_init - initialize hw ecc for device in GPMC controller
+ * @cs: chip select number
+ * @ecc_size: number of bytes for ecc generation
+ */
+
+int gpmc_ecc_init(int cs, int ecc_size)
+{
+ unsigned int val = 0x0;
+
+ /* check if ecc engine already by another cs */
+ if (gpmc_ecc_used == -EINVAL)
+ gpmc_ecc_used = cs;
+ else
+ return -EBUSY;
+
+ /* read ecc control register */
+ val = gpmc_read_reg(GPMC_ECC_CONTROL);
+
+ /* clear ecc and enable bits */
+ val = ((0x00000001<<8) | 0x00000001);
+ gpmc_write_reg(GPMC_ECC_CONTROL, val);
+
+ /* Read from ECC Size Config Register */
+ val = gpmc_read_reg(GPMC_ECC_SIZE_CONFIG);
+
+ /* program ecc and result sizes */
+ val = ((((ecc_size >> 1) - 1) << 22) | (0x0000000F));
+ gpmc_write_reg(GPMC_ECC_SIZE_CONFIG, val);
+
+ return 0;
+}
+
+/**
+ * gpmc_calculate_ecc - generate non-inverted ecc bytes
+ * @cs: chip select number
+ * @dat: data pointer over which ecc is computed
+ * @ecc_code: ecc code buffer
+ *
+ * Using non-inverted ECC is considered ugly since writing a blank
+ * page (padding) will clear the ECC bytes. This is not a problem as long
+ * no one is trying to write data on the seemingly unused page. Reading
+ * an erased page will produce an ECC mismatch between generated and read
+ * ECC bytes that has to be dealt with separately.
+ */
+int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code)
+{
+ unsigned int val = 0x0;
+
+ if (gpmc_ecc_used != cs)
+ return -EINVAL;
+
+ /* read ecc result */
+ val = gpmc_read_reg(GPMC_ECC1_RESULT);
+ *ecc_code++ = val; /* P128e, ..., P1e */
+ *ecc_code++ = val >> 16; /* P128o, ..., P1o */
+ /* P2048o, P1024o, P512o, P256o, P2048e, P1024e, P512e, P256e */
+ *ecc_code++ = ((val >> 8) & 0x0f) | ((val >> 20) & 0xf0);
+
+ return 0;
+}
+
+/**
+ * gpmc_enable_hwecc - enable hardware ecc functionality
+ * @cs: chip select number
+ * @mode: read/write mode
+ * @dev_width: device bus width(1 for x16, 0 for x8)
+ */
+int gpmc_enable_hwecc(int cs, int mode, int dev_width)
+{
+ unsigned int val;
+
+ if (gpmc_ecc_used != cs)
+ return -EINVAL;
+
+ switch (mode) {
+ case GPMC_ECC_READ:
+ gpmc_write_reg(GPMC_ECC_CONTROL, 0x101);
+ break;
+ case GPMC_ECC_READSYN:
+ gpmc_write_reg(GPMC_ECC_CONTROL, 0x100);
+ break;
+ case GPMC_ECC_WRITE:
+ gpmc_write_reg(GPMC_ECC_CONTROL, 0x101);
+ break;
+ default:
+ printk(KERN_INFO "Error: Unrecognized Mode[%d]!\n", mode);
+ break;
+ }
+
+ /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */
+ val = (dev_width << 7) | (cs << 1) | (0x1);
+ gpmc_write_reg(GPMC_ECC_CONFIG, val);
+ return 0;
+}
+
+/**
+ * gmpc_ecc_reset - release the HW ECC in GPMC controller
+ * @cs: Chip select number
+ */
+int gpmc_ecc_reset(int cs)
+{
+ if (gpmc_ecc_used == cs)
+ gpmc_ecc_used = -EINVAL;
+ else
+ return -EINVAL;
+
+ return 0;
+}
+
diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h
index 145838a..67a3442
--- a/arch/arm/plat-omap/include/plat/gpmc.h
+++ b/arch/arm/plat-omap/include/plat/gpmc.h
@@ -27,8 +27,24 @@
#define GPMC_CONFIG 0x50
#define GPMC_STATUS 0x54
-#define GPMC_CS0_BASE 0x60
-#define GPMC_CS_SIZE 0x30
+
+/* Control Commands */
+#define GPMC_CONFIG_WP 0x00000001
+#define GPMC_CONFIG_RDY_BSY 0x00000002
+#define GPMC_CONFIG_DEV_SIZE 0x00000003
+#define GPMC_CONFIG_DEV_TYPE 0x00000004
+#define GPMC_NAND_COMMAND 0x00000005
+#define GPMC_NAND_ADDRESS 0x00000006
+#define GPMC_NAND_DATA 0x00000007
+#define GPMC_STATUS_BUFFER 0x00000008 /* 1: buffer is available to write */
+#define GPMC_PREFETCH_FIFO_CNT 0x00000009 /* bytes available in FIFO for r/w */
+#define GPMC_PREFETCH_COUNT 0x0000000A /* remaining bytes to be read/write*/
+#define GPMC_GET_SET_IRQ_STATUS 0x0000000B
+
+/* ECC commands */
+#define GPMC_ECC_READ 0 /* Reset Hardware ECC for read */
+#define GPMC_ECC_WRITE 1 /* Reset Hardware ECC for write */
+#define GPMC_ECC_READSYN 2 /* Reset before syndrom is read back */
#define GPMC_CONFIG1_WRAPBURST_SUPP (1 << 31)
#define GPMC_CONFIG1_READMULTIPLE_SUPP (1 << 30)
@@ -56,6 +72,14 @@
#define GPMC_CONFIG1_FCLK_DIV4 (GPMC_CONFIG1_FCLK_DIV(3))
#define GPMC_CONFIG7_CSVALID (1 << 6)
+#define GPMC_DEVICETYPE_NOR 0
+#define GPMC_DEVICETYPE_NAND 2
+#define GPMC_CONFIG_WRITEPROTECT 0x00000010
+#define GPMC_STATUS_BUFF_EMPTY 0x00000001
+#define WR_RD_PIN_MONITORING 0x00600000
+#define GPMC_PREFETCH_STATUS_FIFO_CNT(val) ((val & 0x7f000000) >> 24)
+#define GPMC_PREFETCH_STATUS_COUNT(val) (val & 0x00003fff)
+
/*
* Note that all values in this struct are in nanoseconds, while
* the register values are in gpmc_fck cycles.
@@ -108,10 +132,15 @@ extern int gpmc_cs_set_reserved(int cs, int reserved);
extern int gpmc_cs_reserved(int cs);
extern int gpmc_prefetch_enable(int cs, int dma_mode,
unsigned int u32_count, int is_write);
-extern void gpmc_prefetch_reset(void);
+extern int gpmc_prefetch_reset(int cs);
extern int gpmc_prefetch_status(void);
extern void omap3_gpmc_save_context(void);
extern void omap3_gpmc_restore_context(void);
extern void gpmc_init(void);
+extern int gpmc_hwcontrol(int cs, int cmd, int write, int wval, int *rval);
+int gpmc_ecc_init(int cs, int ecc_size);
+int gpmc_enable_hwecc(int cs, int mode, int dev_width);
+int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code);
+int gpmc_ecc_reset(int cs);
#endif
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 7545568..206406b
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -316,7 +316,7 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len)
} while (len);
/* disable and stop the PFPW engine */
- gpmc_prefetch_reset();
+ gpmc_prefetch_reset(info->gpmc_cs);
}
}
@@ -360,7 +360,7 @@ static void omap_write_buf_pref(struct mtd_info *mtd,
}
/* disable and stop the PFPW engine */
- gpmc_prefetch_reset();
+ gpmc_prefetch_reset(info->gpmc_cs);
}
}
^ permalink raw reply related [flat|nested] 102+ messages in thread
* [PATCH v3 2/3] omap3 nand: cleanup virtual address usages
2010-05-18 11:16 ` [PATCH v3 1/3] omap3 gpmc: functionality enhancement Sukumar Ghorai
@ 2010-05-18 11:16 ` Sukumar Ghorai
2010-05-18 11:16 ` [PATCH v3 3/3] omap3 nand: fix issue in board file to detect nand Sukumar Ghorai
2010-05-19 15:30 ` [PATCH v3 2/3] omap3 nand: cleanup virtual address usages Vimal Singh
2010-05-19 14:46 ` [PATCH v3 1/3] omap3 gpmc: functionality enhancement Vimal Singh
1 sibling, 2 replies; 102+ messages in thread
From: Sukumar Ghorai @ 2010-05-18 11:16 UTC (permalink / raw)
To: linux-omap
Cc: linux-mtd, tony, sakoman, mike, Artem.Bityutskiy, Sukumar Ghorai
This patch removes direct reference of gpmc address from generic nand platform code.
Nand platform code now uses wrapper functions which are implemented in gpmc module.
Signed-off-by: Sukumar Ghorai <s-ghorai@ti.com>
---
arch/arm/mach-omap2/gpmc-nand.c | 39 ++----
arch/arm/mach-omap2/gpmc.c | 9 --
arch/arm/plat-omap/include/plat/gpmc.h | 7 +-
arch/arm/plat-omap/include/plat/nand.h | 6 +-
drivers/mtd/nand/omap2.c | 242 ++++++++++----------------------
5 files changed, 88 insertions(+), 215 deletions(-)
diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c
index e57fb29..80f5d94
--- a/arch/arm/mach-omap2/gpmc-nand.c
+++ b/arch/arm/mach-omap2/gpmc-nand.c
@@ -19,8 +19,6 @@
#include <plat/board.h>
#include <plat/gpmc.h>
-#define WR_RD_PIN_MONITORING 0x00600000
-
static struct omap_nand_platform_data *gpmc_nand_data;
static struct resource gpmc_nand_resource = {
@@ -71,10 +69,10 @@ static int omap2_nand_gpmc_retime(void)
t.wr_cycle = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->wr_cycle);
/* Configure GPMC */
- gpmc_cs_write_reg(gpmc_nand_data->cs, GPMC_CS_CONFIG1,
- GPMC_CONFIG1_DEVICESIZE(gpmc_nand_data->devsize) |
- GPMC_CONFIG1_DEVICETYPE_NAND);
-
+ gpmc_hwcontrol(gpmc_nand_data->cs,
+ GPMC_CONFIG_DEV_SIZE, 1, gpmc_nand_data->devsize, NULL);
+ gpmc_hwcontrol(gpmc_nand_data->cs,
+ GPMC_CONFIG_DEV_TYPE, 1, GPMC_DEVICETYPE_NAND, NULL);
err = gpmc_cs_set_timings(gpmc_nand_data->cs, &t);
if (err)
return err;
@@ -82,27 +80,13 @@ static int omap2_nand_gpmc_retime(void)
return 0;
}
-static int gpmc_nand_setup(void)
-{
- struct device *dev = &gpmc_nand_device.dev;
-
- /* Set timings in GPMC */
- if (omap2_nand_gpmc_retime() < 0) {
- dev_err(dev, "Unable to set gpmc timings\n");
- return -EINVAL;
- }
-
- return 0;
-}
-
int __init gpmc_nand_init(struct omap_nand_platform_data *_nand_data)
{
- unsigned int val;
int err = 0;
struct device *dev = &gpmc_nand_device.dev;
gpmc_nand_data = _nand_data;
- gpmc_nand_data->nand_setup = gpmc_nand_setup;
+ gpmc_nand_data->nand_setup = omap2_nand_gpmc_retime;
gpmc_nand_device.dev.platform_data = gpmc_nand_data;
err = gpmc_cs_request(gpmc_nand_data->cs, NAND_IO_SIZE,
@@ -112,19 +96,17 @@ int __init gpmc_nand_init(struct omap_nand_platform_data *_nand_data)
return err;
}
- err = gpmc_nand_setup();
+ /* Set timings in GPMC */
+ err = omap2_nand_gpmc_retime();
if (err < 0) {
- dev_err(dev, "NAND platform setup failed: %d\n", err);
+ dev_err(dev, "Unable to set gpmc timings: %d\n", err);
return err;
}
/* Enable RD PIN Monitoring Reg */
if (gpmc_nand_data->dev_ready) {
- val = gpmc_cs_read_reg(gpmc_nand_data->cs,
- GPMC_CS_CONFIG1);
- val |= WR_RD_PIN_MONITORING;
- gpmc_cs_write_reg(gpmc_nand_data->cs,
- GPMC_CS_CONFIG1, val);
+ gpmc_hwcontrol(gpmc_nand_data->cs,
+ GPMC_CONFIG_RDY_BSY, 1, 1, NULL);
}
err = platform_device_register(&gpmc_nand_device);
@@ -140,3 +122,4 @@ out_free_cs:
return err;
}
+
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index f414aeb..cbe0efb
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -589,15 +589,6 @@ int gpmc_prefetch_reset(int cs)
}
EXPORT_SYMBOL(gpmc_prefetch_reset);
-/**
- * gpmc_prefetch_status - reads prefetch status of engine
- */
-int gpmc_prefetch_status(void)
-{
- return gpmc_read_reg(GPMC_PREFETCH_STATUS);
-}
-EXPORT_SYMBOL(gpmc_prefetch_status);
-
static void __init gpmc_mem_init(void)
{
int cs;
diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h
index 67a3442..2386ff6
--- a/arch/arm/plat-omap/include/plat/gpmc.h
+++ b/arch/arm/plat-omap/include/plat/gpmc.h
@@ -25,9 +25,6 @@
#define GPMC_CS_NAND_ADDRESS 0x20
#define GPMC_CS_NAND_DATA 0x24
-#define GPMC_CONFIG 0x50
-#define GPMC_STATUS 0x54
-
/* Control Commands */
#define GPMC_CONFIG_WP 0x00000001
#define GPMC_CONFIG_RDY_BSY 0x00000002
@@ -63,7 +60,6 @@
#define GPMC_CONFIG1_DEVICESIZE_16 GPMC_CONFIG1_DEVICESIZE(1)
#define GPMC_CONFIG1_DEVICETYPE(val) ((val & 3) << 10)
#define GPMC_CONFIG1_DEVICETYPE_NOR GPMC_CONFIG1_DEVICETYPE(0)
-#define GPMC_CONFIG1_DEVICETYPE_NAND GPMC_CONFIG1_DEVICETYPE(2)
#define GPMC_CONFIG1_MUXADDDATA (1 << 9)
#define GPMC_CONFIG1_TIME_PARA_GRAN (1 << 4)
#define GPMC_CONFIG1_FCLK_DIV(val) (val & 3)
@@ -77,7 +73,7 @@
#define GPMC_CONFIG_WRITEPROTECT 0x00000010
#define GPMC_STATUS_BUFF_EMPTY 0x00000001
#define WR_RD_PIN_MONITORING 0x00600000
-#define GPMC_PREFETCH_STATUS_FIFO_CNT(val) ((val & 0x7f000000) >> 24)
+#define GPMC_PREFETCH_STATUS_FIFO_CNT(val) ((val >> 24) & 0x7F)
#define GPMC_PREFETCH_STATUS_COUNT(val) (val & 0x00003fff)
/*
@@ -133,7 +129,6 @@ extern int gpmc_cs_reserved(int cs);
extern int gpmc_prefetch_enable(int cs, int dma_mode,
unsigned int u32_count, int is_write);
extern int gpmc_prefetch_reset(int cs);
-extern int gpmc_prefetch_status(void);
extern void omap3_gpmc_save_context(void);
extern void omap3_gpmc_restore_context(void);
extern void gpmc_init(void);
diff --git a/arch/arm/plat-omap/include/plat/nand.h b/arch/arm/plat-omap/include/plat/nand.h
index f8efd54..6562cd0
--- a/arch/arm/plat-omap/include/plat/nand.h
+++ b/arch/arm/plat-omap/include/plat/nand.h
@@ -21,13 +21,11 @@ struct omap_nand_platform_data {
int (*dev_ready)(struct omap_nand_platform_data *);
int dma_channel;
unsigned long phys_base;
- void __iomem *gpmc_cs_baseaddr;
- void __iomem *gpmc_baseaddr;
int devsize;
};
-/* size (4 KiB) for IO mapping */
-#define NAND_IO_SIZE SZ_4K
+/* minimum size for IO mapping */
+#define NAND_IO_SIZE 4
#if defined(CONFIG_MTD_NAND_OMAP2) || defined(CONFIG_MTD_NAND_OMAP2_MODULE)
extern int gpmc_nand_init(struct omap_nand_platform_data *d);
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 206406b..e2302a7
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -23,20 +23,8 @@
#include <plat/gpmc.h>
#include <plat/nand.h>
-#define GPMC_IRQ_STATUS 0x18
-#define GPMC_ECC_CONFIG 0x1F4
-#define GPMC_ECC_CONTROL 0x1F8
-#define GPMC_ECC_SIZE_CONFIG 0x1FC
-#define GPMC_ECC1_RESULT 0x200
-
#define DRIVER_NAME "omap2-nand"
-#define NAND_WP_OFF 0
-#define NAND_WP_BIT 0x00000010
-
-#define GPMC_BUF_FULL 0x00000001
-#define GPMC_BUF_EMPTY 0x00000000
-
#define NAND_Ecc_P1e (1 << 0)
#define NAND_Ecc_P2e (1 << 1)
#define NAND_Ecc_P4e (1 << 2)
@@ -139,34 +127,11 @@ struct omap_nand_info {
int gpmc_cs;
unsigned long phys_base;
- void __iomem *gpmc_cs_baseaddr;
- void __iomem *gpmc_baseaddr;
- void __iomem *nand_pref_fifo_add;
struct completion comp;
int dma_ch;
};
/**
- * omap_nand_wp - This function enable or disable the Write Protect feature
- * @mtd: MTD device structure
- * @mode: WP ON/OFF
- */
-static void omap_nand_wp(struct mtd_info *mtd, int mode)
-{
- struct omap_nand_info *info = container_of(mtd,
- struct omap_nand_info, mtd);
-
- unsigned long config = __raw_readl(info->gpmc_baseaddr + GPMC_CONFIG);
-
- if (mode)
- config &= ~(NAND_WP_BIT); /* WP is ON */
- else
- config |= (NAND_WP_BIT); /* WP is OFF */
-
- __raw_writel(config, (info->gpmc_baseaddr + GPMC_CONFIG));
-}
-
-/**
* omap_hwcontrol - hardware specific access to control-lines
* @mtd: MTD device structure
* @cmd: command to device
@@ -181,31 +146,20 @@ static void omap_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
struct omap_nand_info *info = container_of(mtd,
struct omap_nand_info, mtd);
- switch (ctrl) {
- case NAND_CTRL_CHANGE | NAND_CTRL_CLE:
- info->nand.IO_ADDR_W = info->gpmc_cs_baseaddr +
- GPMC_CS_NAND_COMMAND;
- info->nand.IO_ADDR_R = info->gpmc_cs_baseaddr +
- GPMC_CS_NAND_DATA;
- break;
-
- case NAND_CTRL_CHANGE | NAND_CTRL_ALE:
- info->nand.IO_ADDR_W = info->gpmc_cs_baseaddr +
- GPMC_CS_NAND_ADDRESS;
- info->nand.IO_ADDR_R = info->gpmc_cs_baseaddr +
- GPMC_CS_NAND_DATA;
- break;
-
- case NAND_CTRL_CHANGE | NAND_NCE:
- info->nand.IO_ADDR_W = info->gpmc_cs_baseaddr +
- GPMC_CS_NAND_DATA;
- info->nand.IO_ADDR_R = info->gpmc_cs_baseaddr +
- GPMC_CS_NAND_DATA;
- break;
- }
- if (cmd != NAND_CMD_NONE)
- __raw_writeb(cmd, info->nand.IO_ADDR_W);
+ if (cmd != NAND_CMD_NONE) {
+ if (ctrl & NAND_CLE)
+ gpmc_hwcontrol(info->gpmc_cs,
+ GPMC_NAND_COMMAND, 1, cmd, NULL);
+
+ else if (ctrl & NAND_ALE)
+ gpmc_hwcontrol(info->gpmc_cs,
+ GPMC_NAND_ADDRESS, 1, cmd, NULL);
+
+ else /* NAND_NCE */
+ gpmc_hwcontrol(info->gpmc_cs,
+ GPMC_NAND_DATA, 1, cmd, NULL);
+ }
}
/**
@@ -232,11 +186,15 @@ static void omap_write_buf8(struct mtd_info *mtd, const u_char *buf, int len)
struct omap_nand_info *info = container_of(mtd,
struct omap_nand_info, mtd);
u_char *p = (u_char *)buf;
+ u32 status = 0;
while (len--) {
iowrite8(*p++, info->nand.IO_ADDR_W);
- while (GPMC_BUF_EMPTY == (readl(info->gpmc_baseaddr +
- GPMC_STATUS) & GPMC_BUF_FULL));
+ /* wait until buffer is available for write */
+ do {
+ gpmc_hwcontrol(info->gpmc_cs,
+ GPMC_STATUS_BUFFER, 0, 0, &status);
+ } while (!status);
}
}
@@ -264,16 +222,17 @@ static void omap_write_buf16(struct mtd_info *mtd, const u_char * buf, int len)
struct omap_nand_info *info = container_of(mtd,
struct omap_nand_info, mtd);
u16 *p = (u16 *) buf;
-
+ u32 status = 0;
/* FIXME try bursts of writesw() or DMA ... */
len >>= 1;
while (len--) {
iowrite16(*p++, info->nand.IO_ADDR_W);
-
- while (GPMC_BUF_EMPTY == (readl(info->gpmc_baseaddr +
- GPMC_STATUS) & GPMC_BUF_FULL))
- ;
+ /* wait until buffer is available for write */
+ do {
+ gpmc_hwcontrol(info->gpmc_cs,
+ GPMC_STATUS_BUFFER, 0, 0, &status);
+ } while (!status);
}
}
@@ -287,16 +246,15 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len)
{
struct omap_nand_info *info = container_of(mtd,
struct omap_nand_info, mtd);
- uint32_t pfpw_status = 0, r_count = 0;
+ u32 r_count = 0;
int ret = 0;
- u32 *p = (u32 *)buf;
+ u32 *p;
/* take care of subpage reads */
for (; len % 4 != 0; ) {
*buf++ = __raw_readb(info->nand.IO_ADDR_R);
len--;
}
- p = (u32 *) buf;
/* configure and start prefetch transfer */
ret = gpmc_prefetch_enable(info->gpmc_cs, 0x0, len, 0x0);
@@ -307,17 +265,18 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len)
else
omap_read_buf8(mtd, buf, len);
} else {
+ p = (u32 *) buf;
do {
- pfpw_status = gpmc_prefetch_status();
- r_count = ((pfpw_status >> 24) & 0x7F) >> 2;
- ioread32_rep(info->nand_pref_fifo_add, p, r_count);
+ gpmc_hwcontrol(info->gpmc_cs,
+ GPMC_PREFETCH_FIFO_CNT, 0, 0, &r_count);
+ r_count = r_count >> 2;
+ ioread32_rep(info->nand.IO_ADDR_R, p, r_count);
p += r_count;
- len -= r_count << 2;
+ len -= (r_count << 2);
} while (len);
-
- /* disable and stop the PFPW engine */
- gpmc_prefetch_reset(info->gpmc_cs);
}
+ /* disable and stop the PFPW engine */
+ gpmc_prefetch_reset(info->gpmc_cs);
}
/**
@@ -331,13 +290,13 @@ static void omap_write_buf_pref(struct mtd_info *mtd,
{
struct omap_nand_info *info = container_of(mtd,
struct omap_nand_info, mtd);
- uint32_t pfpw_status = 0, w_count = 0;
+ uint32_t pref_count = 0, w_count = 0;
int i = 0, ret = 0;
- u16 *p = (u16 *) buf;
+ u16 *p;
/* take care of subpage writes */
if (len % 2 != 0) {
- writeb(*buf, info->nand.IO_ADDR_R);
+ writeb(*buf, info->nand.IO_ADDR_W);
p = (u16 *)(buf + 1);
len--;
}
@@ -351,17 +310,22 @@ static void omap_write_buf_pref(struct mtd_info *mtd,
else
omap_write_buf8(mtd, buf, len);
} else {
- pfpw_status = gpmc_prefetch_status();
- while (pfpw_status & 0x3FFF) {
- w_count = ((pfpw_status >> 24) & 0x7F) >> 1;
+ p = (u16 *) buf;
+ while (len) {
+ gpmc_hwcontrol(info->gpmc_cs,
+ GPMC_PREFETCH_FIFO_CNT, 0, 0, &w_count);
+ w_count = w_count >> 1;
for (i = 0; (i < w_count) && len; i++, len -= 2)
- iowrite16(*p++, info->nand_pref_fifo_add);
- pfpw_status = gpmc_prefetch_status();
+ iowrite16(*p++, info->nand.IO_ADDR_W);
}
-
- /* disable and stop the PFPW engine */
- gpmc_prefetch_reset(info->gpmc_cs);
+ /* wait for data to flushed-out before reset the prefetch */
+ do {
+ gpmc_hwcontrol(info->gpmc_cs,
+ GPMC_PREFETCH_COUNT, 0, 0, &pref_count);
+ } while (pref_count);
}
+ /* disable and stop the PFPW engine */
+ gpmc_prefetch_reset(info->gpmc_cs);
}
#ifdef CONFIG_MTD_NAND_OMAP_PREFETCH_DMA
@@ -448,8 +412,10 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr,
/* setup and start DMA using dma_addr */
wait_for_completion(&info->comp);
- while (0x3fff & (prefetch_status = gpmc_prefetch_status()))
- ;
+ do {
+ gpmc_hwcontrol(info->gpmc_cs,
+ GPMC_PREFETCH_COUNT, 0, 0, &prefetch_status);
+ } while (prefetch_status);
/* disable and stop the PFPW engine */
gpmc_prefetch_reset();
@@ -502,7 +468,7 @@ static void omap_write_buf_dma_pref(struct mtd_info *mtd,
omap_write_buf_pref(mtd, buf, len);
else
/* start transfer in DMA mode */
- omap_nand_dma_transfer(mtd, buf, len, 0x1);
+ omap_nand_dma_transfer(mtd, (u_char *) buf, len, 0x1);
}
/**
@@ -528,30 +494,6 @@ static int omap_verify_buf(struct mtd_info *mtd, const u_char * buf, int len)
#ifdef CONFIG_MTD_NAND_OMAP_HWECC
/**
- * omap_hwecc_init - Initialize the HW ECC for NAND flash in GPMC controller
- * @mtd: MTD device structure
- */
-static void omap_hwecc_init(struct mtd_info *mtd)
-{
- struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
- mtd);
- struct nand_chip *chip = mtd->priv;
- unsigned long val = 0x0;
-
- /* Read from ECC Control Register */
- val = __raw_readl(info->gpmc_baseaddr + GPMC_ECC_CONTROL);
- /* Clear all ECC | Enable Reg1 */
- val = ((0x00000001<<8) | 0x00000001);
- __raw_writel(val, info->gpmc_baseaddr + GPMC_ECC_CONTROL);
-
- /* Read from ECC Size Config Register */
- val = __raw_readl(info->gpmc_baseaddr + GPMC_ECC_SIZE_CONFIG);
- /* ECCSIZE1=512 | Select eccResultsize[0-3] */
- val = ((((chip->ecc.size >> 1) - 1) << 22) | (0x0000000F));
- __raw_writel(val, info->gpmc_baseaddr + GPMC_ECC_SIZE_CONFIG);
-}
-
-/**
* gen_true_ecc - This function will generate true ECC value
* @ecc_buf: buffer to store ecc code
*
@@ -752,19 +694,7 @@ static int omap_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
{
struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
mtd);
- unsigned long val = 0x0;
- unsigned long reg;
-
- /* Start Reading from HW ECC1_Result = 0x200 */
- reg = (unsigned long)(info->gpmc_baseaddr + GPMC_ECC1_RESULT);
- val = __raw_readl(reg);
- *ecc_code++ = val; /* P128e, ..., P1e */
- *ecc_code++ = val >> 16; /* P128o, ..., P1o */
- /* P2048o, P1024o, P512o, P256o, P2048e, P1024e, P512e, P256e */
- *ecc_code++ = ((val >> 8) & 0x0f) | ((val >> 20) & 0xf0);
- reg += 4;
-
- return 0;
+ return gpmc_calculate_ecc(info->gpmc_cs, dat, ecc_code);
}
/**
@@ -778,32 +708,10 @@ static void omap_enable_hwecc(struct mtd_info *mtd, int mode)
mtd);
struct nand_chip *chip = mtd->priv;
unsigned int dev_width = (chip->options & NAND_BUSWIDTH_16) ? 1 : 0;
- unsigned long val = __raw_readl(info->gpmc_baseaddr + GPMC_ECC_CONFIG);
-
- switch (mode) {
- case NAND_ECC_READ:
- __raw_writel(0x101, info->gpmc_baseaddr + GPMC_ECC_CONTROL);
- /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */
- val = (dev_width << 7) | (info->gpmc_cs << 1) | (0x1);
- break;
- case NAND_ECC_READSYN:
- __raw_writel(0x100, info->gpmc_baseaddr + GPMC_ECC_CONTROL);
- /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */
- val = (dev_width << 7) | (info->gpmc_cs << 1) | (0x1);
- break;
- case NAND_ECC_WRITE:
- __raw_writel(0x101, info->gpmc_baseaddr + GPMC_ECC_CONTROL);
- /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */
- val = (dev_width << 7) | (info->gpmc_cs << 1) | (0x1);
- break;
- default:
- DEBUG(MTD_DEBUG_LEVEL0, "Error: Unrecognized Mode[%d]!\n",
- mode);
- break;
- }
- __raw_writel(val, info->gpmc_baseaddr + GPMC_ECC_CONFIG);
+ gpmc_enable_hwecc(info->gpmc_cs, mode, dev_width);
}
+
#endif
/**
@@ -831,14 +739,10 @@ static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip)
else
timeo += (HZ * 20) / 1000;
- this->IO_ADDR_W = (void *) info->gpmc_cs_baseaddr +
- GPMC_CS_NAND_COMMAND;
- this->IO_ADDR_R = (void *) info->gpmc_cs_baseaddr + GPMC_CS_NAND_DATA;
-
- __raw_writeb(NAND_CMD_STATUS & 0xFF, this->IO_ADDR_W);
-
+ gpmc_hwcontrol(info->gpmc_cs,
+ GPMC_NAND_COMMAND, 1, (NAND_CMD_STATUS & 0xFF), NULL);
while (time_before(jiffies, timeo)) {
- status = __raw_readb(this->IO_ADDR_R);
+ gpmc_hwcontrol(info->gpmc_cs, GPMC_NAND_DATA, 0, 0, &status);
if (status & NAND_STATUS_READY)
break;
cond_resched();
@@ -852,22 +756,24 @@ static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip)
*/
static int omap_dev_ready(struct mtd_info *mtd)
{
+ unsigned int val = 0;
struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
mtd);
- unsigned int val = __raw_readl(info->gpmc_baseaddr + GPMC_IRQ_STATUS);
+ gpmc_hwcontrol(info->gpmc_cs, GPMC_GET_SET_IRQ_STATUS, 0, 0, &val);
if ((val & 0x100) == 0x100) {
/* Clear IRQ Interrupt */
val |= 0x100;
val &= ~(0x0);
- __raw_writel(val, info->gpmc_baseaddr + GPMC_IRQ_STATUS);
+ gpmc_hwcontrol(info->gpmc_cs,
+ GPMC_GET_SET_IRQ_STATUS, 1, val, NULL);
} else {
unsigned int cnt = 0;
while (cnt++ < 0x1FF) {
if ((val & 0x100) == 0x100)
return 0;
- val = __raw_readl(info->gpmc_baseaddr +
- GPMC_IRQ_STATUS);
+ gpmc_hwcontrol(info->gpmc_cs,
+ GPMC_GET_SET_IRQ_STATUS, 0, 0, &val);
}
}
@@ -898,8 +804,6 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
info->pdev = pdev;
info->gpmc_cs = pdata->cs;
- info->gpmc_baseaddr = pdata->gpmc_baseaddr;
- info->gpmc_cs_baseaddr = pdata->gpmc_cs_baseaddr;
info->phys_base = pdata->phys_base;
info->mtd.priv = &info->nand;
@@ -910,7 +814,7 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
info->nand.options |= NAND_SKIP_BBTSCAN;
/* NAND write protect off */
- omap_nand_wp(&info->mtd, NAND_WP_OFF);
+ gpmc_hwcontrol(info->gpmc_cs, GPMC_CONFIG_WP, 1, 0, NULL);
if (!request_mem_region(info->phys_base, NAND_IO_SIZE,
pdev->dev.driver->name)) {
@@ -946,7 +850,6 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
if (use_prefetch) {
/* copy the virtual address of nand base for fifo access */
- info->nand_pref_fifo_add = info->nand.IO_ADDR_R;
info->nand.read_buf = omap_read_buf_pref;
info->nand.write_buf = omap_write_buf_pref;
@@ -987,7 +890,7 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
info->nand.ecc.mode = NAND_ECC_HW;
/* init HW ECC */
- omap_hwecc_init(&info->mtd);
+ gpmc_ecc_init(info->gpmc_cs, info->nand.ecc.size);
#else
info->nand.ecc.mode = NAND_ECC_SOFT;
#endif
@@ -1034,9 +937,12 @@ static int omap_nand_remove(struct platform_device *pdev)
if (use_dma)
omap_free_dma(info->dma_ch);
+ /* reset/ releae the ecc module */
+ gpmc_ecc_reset(info->gpmc_cs);
+
/* Release NAND device, its internal structures and partitions */
nand_release(&info->mtd);
- iounmap(info->nand_pref_fifo_add);
+ iounmap(info->nand.IO_ADDR_R);
kfree(&info->mtd);
return 0;
}
^ permalink raw reply related [flat|nested] 102+ messages in thread
* [PATCH v3 3/3] omap3 nand: fix issue in board file to detect nand
2010-05-18 11:16 ` [PATCH v3 2/3] omap3 nand: cleanup virtual address usages Sukumar Ghorai
@ 2010-05-18 11:16 ` Sukumar Ghorai
2010-05-19 15:30 ` [PATCH v3 2/3] omap3 nand: cleanup virtual address usages Vimal Singh
1 sibling, 0 replies; 102+ messages in thread
From: Sukumar Ghorai @ 2010-05-18 11:16 UTC (permalink / raw)
To: linux-omap
Cc: linux-mtd, tony, sakoman, mike, Artem.Bityutskiy, Sukumar Ghorai
Board file modified for not to provide gpmc phys_base address to nand driver.
The gpmc_nand_init funciton is now used to detect the nand and required to
adopt _prob function as in nand/omap2.c
Signed-off-by: Sukumar Ghorai <s-ghorai@ti.com>
---
arch/arm/mach-omap2/board-cm-t35.c | 20 +-------------------
arch/arm/mach-omap2/board-devkit8000.c | 25 +------------------------
arch/arm/mach-omap2/board-omap3beagle.c | 24 +-----------------------
arch/arm/mach-omap2/board-omap3touchbook.c | 25 +------------------------
arch/arm/mach-omap2/board-overo.c | 24 +-----------------------
5 files changed, 5 insertions(+), 113 deletions(-)
diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c
index f4e8063..8a41268
--- a/arch/arm/mach-omap2/board-cm-t35.c
+++ b/arch/arm/mach-omap2/board-cm-t35.c
@@ -61,8 +61,6 @@
#define SB_T35_SMSC911X_GPIO 65
#define NAND_BLOCK_SIZE SZ_128K
-#define GPMC_CS0_BASE 0x60
-#define GPMC_CS0_BASE_ADDR (OMAP34XX_GPMC_VIRT + GPMC_CS0_BASE)
#if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
#include <linux/smsc911x.h>
@@ -223,28 +221,12 @@ static struct omap_nand_platform_data cm_t35_nand_data = {
.nr_parts = ARRAY_SIZE(cm_t35_nand_partitions),
.dma_channel = -1, /* disable DMA in OMAP NAND driver */
.cs = 0,
- .gpmc_cs_baseaddr = (void __iomem *)GPMC_CS0_BASE_ADDR,
- .gpmc_baseaddr = (void __iomem *)OMAP34XX_GPMC_VIRT,
};
-static struct resource cm_t35_nand_resource = {
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device cm_t35_nand_device = {
- .name = "omap2-nand",
- .id = -1,
- .num_resources = 1,
- .resource = &cm_t35_nand_resource,
- .dev = {
- .platform_data = &cm_t35_nand_data,
- },
-};
-
static void __init cm_t35_init_nand(void)
{
- if (platform_device_register(&cm_t35_nand_device) < 0)
+ if (gpmc_nand_init(&cm_t35_nand_data) < 0)
pr_err("CM-T35: Unable to register NAND device\n");
}
#else
diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c
index 6d910df..b172414
--- a/arch/arm/mach-omap2/board-devkit8000.c
+++ b/arch/arm/mach-omap2/board-devkit8000.c
@@ -58,9 +58,6 @@
#include "mux.h"
#include "hsmmc.h"
-#define GPMC_CS0_BASE 0x60
-#define GPMC_CS_SIZE 0x30
-
#define NAND_BLOCK_SIZE SZ_128K
#define OMAP_DM9000_GPIO_IRQ 25
@@ -104,20 +101,6 @@ static struct omap_nand_platform_data devkit8000_nand_data = {
.dma_channel = -1, /* disable DMA in OMAP NAND driver */
};
-static struct resource devkit8000_nand_resource = {
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device devkit8000_nand_device = {
- .name = "omap2-nand",
- .id = -1,
- .dev = {
- .platform_data = &devkit8000_nand_data,
- },
- .num_resources = 1,
- .resource = &devkit8000_nand_resource,
-};
-
static struct omap2_hsmmc_info mmc[] = {
{
.mmc = 1,
@@ -581,8 +564,6 @@ static void __init devkit8000_flash_init(void)
u8 cs = 0;
u8 nandcs = GPMC_CS_NUM + 1;
- u32 gpmc_base_add = OMAP34XX_GPMC_VIRT;
-
/* find out the chip-select on which NAND exists */
while (cs < GPMC_CS_NUM) {
u32 ret = 0;
@@ -604,13 +585,9 @@ static void __init devkit8000_flash_init(void)
if (nandcs < GPMC_CS_NUM) {
devkit8000_nand_data.cs = nandcs;
- devkit8000_nand_data.gpmc_cs_baseaddr = (void *)
- (gpmc_base_add + GPMC_CS0_BASE + nandcs * GPMC_CS_SIZE);
- devkit8000_nand_data.gpmc_baseaddr = (void *)
- (gpmc_base_add);
printk(KERN_INFO "Registering NAND on CS%d\n", nandcs);
- if (platform_device_register(&devkit8000_nand_device) < 0)
+ if (gpmc_nand_init(&devkit8000_nand_data) < 0)
printk(KERN_ERR "Unable to register NAND device\n");
}
}
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index 5df89f6..9ec3ef8 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -47,9 +47,6 @@
#include "mux.h"
#include "hsmmc.h"
-#define GPMC_CS0_BASE 0x60
-#define GPMC_CS_SIZE 0x30
-
#define NAND_BLOCK_SIZE SZ_128K
static struct mtd_partition omap3beagle_nand_partitions[] = {
@@ -92,20 +89,6 @@ static struct omap_nand_platform_data omap3beagle_nand_data = {
.dev_ready = NULL,
};
-static struct resource omap3beagle_nand_resource = {
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device omap3beagle_nand_device = {
- .name = "omap2-nand",
- .id = -1,
- .dev = {
- .platform_data = &omap3beagle_nand_data,
- },
- .num_resources = 1,
- .resource = &omap3beagle_nand_resource,
-};
-
#include "sdram-micron-mt46h32m32lf-6.h"
static struct omap2_hsmmc_info mmc[] = {
@@ -377,8 +360,6 @@ static void __init omap3beagle_flash_init(void)
u8 cs = 0;
u8 nandcs = GPMC_CS_NUM + 1;
- u32 gpmc_base_add = OMAP34XX_GPMC_VIRT;
-
/* find out the chip-select on which NAND exists */
while (cs < GPMC_CS_NUM) {
u32 ret = 0;
@@ -400,12 +381,9 @@ static void __init omap3beagle_flash_init(void)
if (nandcs < GPMC_CS_NUM) {
omap3beagle_nand_data.cs = nandcs;
- omap3beagle_nand_data.gpmc_cs_baseaddr = (void *)
- (gpmc_base_add + GPMC_CS0_BASE + nandcs * GPMC_CS_SIZE);
- omap3beagle_nand_data.gpmc_baseaddr = (void *) (gpmc_base_add);
printk(KERN_INFO "Registering NAND on CS%d\n", nandcs);
- if (platform_device_register(&omap3beagle_nand_device) < 0)
+ if (gpmc_nand_init(&omap3beagle_nand_data) < 0)
printk(KERN_ERR "Unable to register NAND device\n");
}
}
diff --git a/arch/arm/mach-omap2/board-omap3touchbook.c b/arch/arm/mach-omap2/board-omap3touchbook.c
index c59050d..29dd266
--- a/arch/arm/mach-omap2/board-omap3touchbook.c
+++ b/arch/arm/mach-omap2/board-omap3touchbook.c
@@ -54,9 +54,6 @@
#include <asm/setup.h>
-#define GPMC_CS0_BASE 0x60
-#define GPMC_CS_SIZE 0x30
-
#define NAND_BLOCK_SIZE SZ_128K
#define OMAP3_AC_GPIO 136
@@ -106,20 +103,6 @@ static struct omap_nand_platform_data omap3touchbook_nand_data = {
.dev_ready = NULL,
};
-static struct resource omap3touchbook_nand_resource = {
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device omap3touchbook_nand_device = {
- .name = "omap2-nand",
- .id = -1,
- .dev = {
- .platform_data = &omap3touchbook_nand_data,
- },
- .num_resources = 1,
- .resource = &omap3touchbook_nand_resource,
-};
-
#include "sdram-micron-mt46h32m32lf-6.h"
static struct omap2_hsmmc_info mmc[] = {
@@ -459,8 +442,6 @@ static void __init omap3touchbook_flash_init(void)
u8 cs = 0;
u8 nandcs = GPMC_CS_NUM + 1;
- u32 gpmc_base_add = OMAP34XX_GPMC_VIRT;
-
/* find out the chip-select on which NAND exists */
while (cs < GPMC_CS_NUM) {
u32 ret = 0;
@@ -482,13 +463,9 @@ static void __init omap3touchbook_flash_init(void)
if (nandcs < GPMC_CS_NUM) {
omap3touchbook_nand_data.cs = nandcs;
- omap3touchbook_nand_data.gpmc_cs_baseaddr = (void *)
- (gpmc_base_add + GPMC_CS0_BASE + nandcs * GPMC_CS_SIZE);
- omap3touchbook_nand_data.gpmc_baseaddr =
- (void *) (gpmc_base_add);
printk(KERN_INFO "Registering NAND on CS%d\n", nandcs);
- if (platform_device_register(&omap3touchbook_nand_device) < 0)
+ if (gpmc_nand_init(&omap3touchbook_nand_data) < 0)
printk(KERN_ERR "Unable to register NAND device\n");
}
}
diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
index 24b32d7..df0fb0d
--- a/arch/arm/mach-omap2/board-overo.c
+++ b/arch/arm/mach-omap2/board-overo.c
@@ -58,8 +58,6 @@
#define OVERO_GPIO_USBH_NRESET 183
#define NAND_BLOCK_SIZE SZ_128K
-#define GPMC_CS0_BASE 0x60
-#define GPMC_CS_SIZE 0x30
#define OVERO_SMSC911X_CS 5
#define OVERO_SMSC911X_GPIO 176
@@ -231,28 +229,11 @@ static struct omap_nand_platform_data overo_nand_data = {
.dma_channel = -1, /* disable DMA in OMAP NAND driver */
};
-static struct resource overo_nand_resource = {
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device overo_nand_device = {
- .name = "omap2-nand",
- .id = -1,
- .dev = {
- .platform_data = &overo_nand_data,
- },
- .num_resources = 1,
- .resource = &overo_nand_resource,
-};
-
-
static void __init overo_flash_init(void)
{
u8 cs = 0;
u8 nandcs = GPMC_CS_NUM + 1;
- u32 gpmc_base_add = OMAP34XX_GPMC_VIRT;
-
/* find out the chip-select on which NAND exists */
while (cs < GPMC_CS_NUM) {
u32 ret = 0;
@@ -274,12 +255,9 @@ static void __init overo_flash_init(void)
if (nandcs < GPMC_CS_NUM) {
overo_nand_data.cs = nandcs;
- overo_nand_data.gpmc_cs_baseaddr = (void *)
- (gpmc_base_add + GPMC_CS0_BASE + nandcs * GPMC_CS_SIZE);
- overo_nand_data.gpmc_baseaddr = (void *) (gpmc_base_add);
printk(KERN_INFO "Registering NAND on CS%d\n", nandcs);
- if (platform_device_register(&overo_nand_device) < 0)
+ if (gpmc_nand_init(&overo_nand_data) < 0)
printk(KERN_ERR "Unable to register NAND device\n");
}
}
^ permalink raw reply related [flat|nested] 102+ messages in thread
* Re: [PATCH v3 1/3] omap3 gpmc: functionality enhancement
2010-05-18 11:16 ` [PATCH v3 1/3] omap3 gpmc: functionality enhancement Sukumar Ghorai
2010-05-18 11:16 ` [PATCH v3 2/3] omap3 nand: cleanup virtual address usages Sukumar Ghorai
@ 2010-05-19 14:46 ` Vimal Singh
2010-05-19 15:14 ` Peter Barada
2010-05-19 15:48 ` Peter Barada
1 sibling, 2 replies; 102+ messages in thread
From: Vimal Singh @ 2010-05-19 14:46 UTC (permalink / raw)
To: Sukumar Ghorai
Cc: linux-omap, linux-mtd, tony, sakoman, mike, Artem.Bityutskiy
On Tue, May 18, 2010 at 4:46 PM, Sukumar Ghorai <s-ghorai@ti.com> wrote:
> few functions added in gpmc module and to be used by other drivers like NAND.
> E.g.: - ioctl function
> - ecc functions
>
> Signed-off-by: Sukumar Ghorai <s-ghorai@ti.com>
> ---
> arch/arm/mach-omap2/gpmc.c | 246 +++++++++++++++++++++++++++++++-
> arch/arm/plat-omap/include/plat/gpmc.h | 35 ++++-
> drivers/mtd/nand/omap2.c | 4 +-
> 3 files changed, 274 insertions(+), 11 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
> index 5bc3ca0..7e6d821
> --- a/arch/arm/mach-omap2/gpmc.c
> +++ b/arch/arm/mach-omap2/gpmc.c
> @@ -46,8 +46,9 @@
> #define GPMC_ECC_CONFIG 0x1f4
> #define GPMC_ECC_CONTROL 0x1f8
> #define GPMC_ECC_SIZE_CONFIG 0x1fc
> +#define GPMC_ECC1_RESULT 0x200
>
> -#define GPMC_CS0 0x60
> +#define GPMC_CS0_BASE 0x60
> #define GPMC_CS_SIZE 0x30
>
> #define GPMC_MEM_START 0x00000000
> @@ -92,7 +93,9 @@ struct omap3_gpmc_regs {
> static struct resource gpmc_mem_root;
> static struct resource gpmc_cs_mem[GPMC_CS_NUM];
> static DEFINE_SPINLOCK(gpmc_mem_lock);
> -static unsigned gpmc_cs_map;
> +static unsigned int gpmc_cs_map; /* flag for cs which are initialized */
> +static int gpmc_pref_used = -EINVAL; /* cs using prefetch engine */
> +static int gpmc_ecc_used = -EINVAL; /* cs using ecc engine */
>
> static void __iomem *gpmc_base;
>
> @@ -108,11 +111,27 @@ static u32 gpmc_read_reg(int idx)
> return __raw_readl(gpmc_base + idx);
> }
>
> +static void gpmc_cs_write_byte(int cs, int idx, u8 val)
> +{
> + void __iomem *reg_addr;
> +
> + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx;
> + __raw_writeb(val, reg_addr);
> +}
> +
> +static u8 gpmc_cs_read_byte(int cs, int idx)
> +{
> + void __iomem *reg_addr;
> +
> + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx;
> + return __raw_readb(reg_addr);
> +}
> +
> void gpmc_cs_write_reg(int cs, int idx, u32 val)
> {
> void __iomem *reg_addr;
>
> - reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx;
> + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx;
> __raw_writel(val, reg_addr);
> }
>
> @@ -120,7 +139,7 @@ u32 gpmc_cs_read_reg(int cs, int idx)
> {
> void __iomem *reg_addr;
>
> - reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx;
> + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx;
> return __raw_readl(reg_addr);
> }
>
> @@ -419,8 +438,100 @@ void gpmc_cs_free(int cs)
> EXPORT_SYMBOL(gpmc_cs_free);
>
> /**
> + * gpmc_hwcontrol - hardware specific access (read/ write) control
> + * @cs: chip select number
> + * @cmd: command type
> + * @write: 1 for write; 0 for read
> + * @wval: value to write
> + * @rval: read pointer
> + */
> +int gpmc_hwcontrol(int cs, int cmd, int write, int wval, int *rval)
> +{
> + u32 regval = 0;
> +
> + if (!write && !rval)
> + return -EINVAL;
> +
> + switch (cmd) {
> + case GPMC_STATUS_BUFFER:
> + regval = gpmc_read_reg(GPMC_STATUS);
> + /* 1 : buffer is available to write */
> + *rval = regval & GPMC_STATUS_BUFF_EMPTY;
> + break;
> +
> + case GPMC_GET_SET_IRQ_STATUS:
> + if (write)
> + gpmc_write_reg(GPMC_IRQSTATUS, wval);
> + else
> + *rval = gpmc_read_reg(GPMC_IRQSTATUS);
> + break;
> +
> + case GPMC_PREFETCH_FIFO_CNT:
> + regval = gpmc_read_reg(GPMC_PREFETCH_STATUS);
> + *rval = GPMC_PREFETCH_STATUS_FIFO_CNT(regval);
> + break;
> +
> + case GPMC_PREFETCH_COUNT:
> + regval = gpmc_read_reg(GPMC_PREFETCH_STATUS);
> + *rval = GPMC_PREFETCH_STATUS_COUNT(regval);
> + break;
> +
> + case GPMC_CONFIG_WP:
> + regval = gpmc_read_reg(GPMC_CONFIG);
> + if (wval)
> + regval &= ~GPMC_CONFIG_WRITEPROTECT; /* WP is ON */
> + else
> + regval |= GPMC_CONFIG_WRITEPROTECT; /* WP is OFF */
> + gpmc_write_reg(GPMC_CONFIG, regval);
> + break;
> +
> + case GPMC_CONFIG_RDY_BSY:
> + regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
> + regval |= WR_RD_PIN_MONITORING;
> + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
> + break;
IIRC, at least in OMAP2/3, ready/busy pin is not in use (not connected).
> +
> + case GPMC_CONFIG_DEV_SIZE:
> + regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
> + regval |= GPMC_CONFIG1_DEVICESIZE(wval);
> + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
> + break;
> +
> + case GPMC_CONFIG_DEV_TYPE:
> + regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
> + regval |= GPMC_CONFIG1_DEVICETYPE(wval);
> + if (wval == GPMC_DEVICETYPE_NOR)
> + regval |= GPMC_CONFIG1_MUXADDDATA;
> + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
> + break;
> +
> + case GPMC_NAND_COMMAND:
> + gpmc_cs_write_byte(cs, GPMC_CS_NAND_COMMAND, wval);
> + break;
> +
> + case GPMC_NAND_ADDRESS:
> + gpmc_cs_write_byte(cs, GPMC_CS_NAND_ADDRESS, wval);
> + break;
> +
> + case GPMC_NAND_DATA:
> + if (write)
> + gpmc_cs_write_byte(cs, GPMC_CS_NAND_DATA, wval);
> + else
> + *rval = gpmc_cs_read_byte(cs, GPMC_CS_NAND_DATA);
> + break;
> +
> + default:
> + printk(KERN_ERR "gpmc_hwcontrol: Not supported\n");
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +EXPORT_SYMBOL(gpmc_hwcontrol);
> +
> +/**
> * gpmc_prefetch_enable - configures and starts prefetch transfer
> - * @cs: nand cs (chip select) number
> + * @cs: cs (chip select) number
> * @dma_mode: dma mode enable (1) or disable (0)
> * @u32_count: number of bytes to be transferred
> * @is_write: prefetch read(0) or write post(1) mode
> @@ -430,6 +541,11 @@ int gpmc_prefetch_enable(int cs, int dma_mode,
> {
> uint32_t prefetch_config1;
>
> + if (gpmc_pref_used == -EINVAL)
> + gpmc_pref_used = cs;
> + else
> + return -EBUSY;
This is not required. Prefetch engine has just one instance
> +
> if (!(gpmc_read_reg(GPMC_PREFETCH_CONTROL))) {
and any prefetch request will be done only if above check passes.
Which actually checks if 'prefetch' is busy or not.
You can see in NAND driver (omap2.c) code, it understands that.
> /* Set the amount of bytes to be prefetched */
> gpmc_write_reg(GPMC_PREFETCH_CONFIG2, u32_count);
> @@ -456,13 +572,20 @@ EXPORT_SYMBOL(gpmc_prefetch_enable);
> /**
> * gpmc_prefetch_reset - disables and stops the prefetch engine
> */
> -void gpmc_prefetch_reset(void)
> +int gpmc_prefetch_reset(int cs)
> {
> + if (gpmc_pref_used == cs)
> + gpmc_pref_used = -EINVAL;
> + else
> + return -EINVAL;
> +
This is also not required. As, this function will be called only if
prefetch was used.
> /* Stop the PFPW engine */
> gpmc_write_reg(GPMC_PREFETCH_CONTROL, 0x0);
>
> /* Reset/disable the PFPW engine */
> gpmc_write_reg(GPMC_PREFETCH_CONFIG1, 0x0);
> +
> + return 0;
> }
> EXPORT_SYMBOL(gpmc_prefetch_reset);
>
> @@ -615,3 +738,114 @@ void omap3_gpmc_restore_context(void)
> }
> }
> #endif /* CONFIG_ARCH_OMAP3 */
> +
> +/**
> + * gpmc_ecc_init - initialize hw ecc for device in GPMC controller
> + * @cs: chip select number
> + * @ecc_size: number of bytes for ecc generation
> + */
> +
> +int gpmc_ecc_init(int cs, int ecc_size)
> +{
> + unsigned int val = 0x0;
> +
> + /* check if ecc engine already by another cs */
> + if (gpmc_ecc_used == -EINVAL)
> + gpmc_ecc_used = cs;
> + else
> + return -EBUSY;
Here few things need be to consider:
1. 'init' is supposed to done once for every instance of driver during probe
2. But ECC engine, too, have only one instance at a time, So
3. As long as all NAND chip are supposed to use same ECC machenism, we
can go for only one time 'init' for all drivers, perhaps in
gpmc_nand.c.
4. But in case, different instances of driver (or NAND chip) requires
different ECC machenism (for ex. Hamming or BCH, or even with
different capabilities of error correction),
this will no longer vailid. Then rather we should have something like
'gpmc_ecc_config' call to configer ECC engine for everytime a driver
needs it (something like as it is done for prefetch engine).
> +
> + /* read ecc control register */
> + val = gpmc_read_reg(GPMC_ECC_CONTROL);
> +
> + /* clear ecc and enable bits */
> + val = ((0x00000001<<8) | 0x00000001);
> + gpmc_write_reg(GPMC_ECC_CONTROL, val);
> +
> + /* Read from ECC Size Config Register */
> + val = gpmc_read_reg(GPMC_ECC_SIZE_CONFIG);
> +
> + /* program ecc and result sizes */
> + val = ((((ecc_size >> 1) - 1) << 22) | (0x0000000F));
> + gpmc_write_reg(GPMC_ECC_SIZE_CONFIG, val);
> +
> + return 0;
> +}
> +
> +/**
> + * gpmc_calculate_ecc - generate non-inverted ecc bytes
> + * @cs: chip select number
> + * @dat: data pointer over which ecc is computed
> + * @ecc_code: ecc code buffer
> + *
> + * Using non-inverted ECC is considered ugly since writing a blank
> + * page (padding) will clear the ECC bytes. This is not a problem as long
> + * no one is trying to write data on the seemingly unused page. Reading
> + * an erased page will produce an ECC mismatch between generated and read
> + * ECC bytes that has to be dealt with separately.
> + */
> +int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code)
> +{
> + unsigned int val = 0x0;
> +
> + if (gpmc_ecc_used != cs)
> + return -EINVAL;
> +
> + /* read ecc result */
> + val = gpmc_read_reg(GPMC_ECC1_RESULT);
> + *ecc_code++ = val; /* P128e, ..., P1e */
> + *ecc_code++ = val >> 16; /* P128o, ..., P1o */
> + /* P2048o, P1024o, P512o, P256o, P2048e, P1024e, P512e, P256e */
> + *ecc_code++ = ((val >> 8) & 0x0f) | ((val >> 20) & 0xf0);
> +
> + return 0;
> +}
> +
> +/**
> + * gpmc_enable_hwecc - enable hardware ecc functionality
> + * @cs: chip select number
> + * @mode: read/write mode
> + * @dev_width: device bus width(1 for x16, 0 for x8)
> + */
> +int gpmc_enable_hwecc(int cs, int mode, int dev_width)
> +{
> + unsigned int val;
> +
> + if (gpmc_ecc_used != cs)
> + return -EINVAL;
> +
> + switch (mode) {
> + case GPMC_ECC_READ:
> + gpmc_write_reg(GPMC_ECC_CONTROL, 0x101);
> + break;
> + case GPMC_ECC_READSYN:
> + gpmc_write_reg(GPMC_ECC_CONTROL, 0x100);
> + break;
> + case GPMC_ECC_WRITE:
> + gpmc_write_reg(GPMC_ECC_CONTROL, 0x101);
> + break;
> + default:
> + printk(KERN_INFO "Error: Unrecognized Mode[%d]!\n", mode);
> + break;
> + }
> +
> + /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */
> + val = (dev_width << 7) | (cs << 1) | (0x1);
> + gpmc_write_reg(GPMC_ECC_CONFIG, val);
> + return 0;
> +}
> +
> +/**
> + * gmpc_ecc_reset - release the HW ECC in GPMC controller
> + * @cs: Chip select number
> + */
> +int gpmc_ecc_reset(int cs)
> +{
> + if (gpmc_ecc_used == cs)
> + gpmc_ecc_used = -EINVAL;
> + else
> + return -EINVAL;
> +
> + return 0;
> +}
> +
> diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h
> index 145838a..67a3442
> --- a/arch/arm/plat-omap/include/plat/gpmc.h
> +++ b/arch/arm/plat-omap/include/plat/gpmc.h
> @@ -27,8 +27,24 @@
>
> #define GPMC_CONFIG 0x50
> #define GPMC_STATUS 0x54
> -#define GPMC_CS0_BASE 0x60
> -#define GPMC_CS_SIZE 0x30
> +
> +/* Control Commands */
> +#define GPMC_CONFIG_WP 0x00000001
> +#define GPMC_CONFIG_RDY_BSY 0x00000002
> +#define GPMC_CONFIG_DEV_SIZE 0x00000003
> +#define GPMC_CONFIG_DEV_TYPE 0x00000004
> +#define GPMC_NAND_COMMAND 0x00000005
> +#define GPMC_NAND_ADDRESS 0x00000006
> +#define GPMC_NAND_DATA 0x00000007
> +#define GPMC_STATUS_BUFFER 0x00000008 /* 1: buffer is available to write */
> +#define GPMC_PREFETCH_FIFO_CNT 0x00000009 /* bytes available in FIFO for r/w */
> +#define GPMC_PREFETCH_COUNT 0x0000000A /* remaining bytes to be read/write*/
> +#define GPMC_GET_SET_IRQ_STATUS 0x0000000B
> +
> +/* ECC commands */
> +#define GPMC_ECC_READ 0 /* Reset Hardware ECC for read */
> +#define GPMC_ECC_WRITE 1 /* Reset Hardware ECC for write */
> +#define GPMC_ECC_READSYN 2 /* Reset before syndrom is read back */
>
> #define GPMC_CONFIG1_WRAPBURST_SUPP (1 << 31)
> #define GPMC_CONFIG1_READMULTIPLE_SUPP (1 << 30)
> @@ -56,6 +72,14 @@
> #define GPMC_CONFIG1_FCLK_DIV4 (GPMC_CONFIG1_FCLK_DIV(3))
> #define GPMC_CONFIG7_CSVALID (1 << 6)
>
> +#define GPMC_DEVICETYPE_NOR 0
> +#define GPMC_DEVICETYPE_NAND 2
> +#define GPMC_CONFIG_WRITEPROTECT 0x00000010
> +#define GPMC_STATUS_BUFF_EMPTY 0x00000001
> +#define WR_RD_PIN_MONITORING 0x00600000
> +#define GPMC_PREFETCH_STATUS_FIFO_CNT(val) ((val & 0x7f000000) >> 24)
> +#define GPMC_PREFETCH_STATUS_COUNT(val) (val & 0x00003fff)
> +
> /*
> * Note that all values in this struct are in nanoseconds, while
> * the register values are in gpmc_fck cycles.
> @@ -108,10 +132,15 @@ extern int gpmc_cs_set_reserved(int cs, int reserved);
> extern int gpmc_cs_reserved(int cs);
> extern int gpmc_prefetch_enable(int cs, int dma_mode,
> unsigned int u32_count, int is_write);
> -extern void gpmc_prefetch_reset(void);
> +extern int gpmc_prefetch_reset(int cs);
> extern int gpmc_prefetch_status(void);
> extern void omap3_gpmc_save_context(void);
> extern void omap3_gpmc_restore_context(void);
> extern void gpmc_init(void);
> +extern int gpmc_hwcontrol(int cs, int cmd, int write, int wval, int *rval);
>
> +int gpmc_ecc_init(int cs, int ecc_size);
> +int gpmc_enable_hwecc(int cs, int mode, int dev_width);
> +int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code);
> +int gpmc_ecc_reset(int cs);
> #endif
> diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
> index 7545568..206406b
> --- a/drivers/mtd/nand/omap2.c
> +++ b/drivers/mtd/nand/omap2.c
> @@ -316,7 +316,7 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len)
> } while (len);
>
> /* disable and stop the PFPW engine */
> - gpmc_prefetch_reset();
> + gpmc_prefetch_reset(info->gpmc_cs);
Not required. see above comments.
> }
> }
>
> @@ -360,7 +360,7 @@ static void omap_write_buf_pref(struct mtd_info *mtd,
> }
>
> /* disable and stop the PFPW engine */
> - gpmc_prefetch_reset();
> + gpmc_prefetch_reset(info->gpmc_cs);
Not required. see above comments.
> }
> }
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
--
Regards,
Vimal Singh
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 102+ messages in thread
* Re: [PATCH v3 1/3] omap3 gpmc: functionality enhancement
2010-05-19 14:46 ` [PATCH v3 1/3] omap3 gpmc: functionality enhancement Vimal Singh
@ 2010-05-19 15:14 ` Peter Barada
2010-05-19 15:48 ` Peter Barada
1 sibling, 0 replies; 102+ messages in thread
From: Peter Barada @ 2010-05-19 15:14 UTC (permalink / raw)
To: Vimal Singh
Cc: Artem.Bityutskiy, tony, Sukumar Ghorai, sakoman, linux-mtd,
linux-omap
On Wed, 2010-05-19 at 20:16 +0530, Vimal Singh wrote:
> On Tue, May 18, 2010 at 4:46 PM, Sukumar Ghorai <s-ghorai@ti.com> wrote:
> > few functions added in gpmc module and to be used by other drivers like NAND.
> > E.g.: - ioctl function
> > - ecc functions
> >
> > Signed-off-by: Sukumar Ghorai <s-ghorai@ti.com>
> > ---
> > arch/arm/mach-omap2/gpmc.c | 246 +++++++++++++++++++++++++++++++-
> > arch/arm/plat-omap/include/plat/gpmc.h | 35 ++++-
> > drivers/mtd/nand/omap2.c | 4 +-
> > 3 files changed, 274 insertions(+), 11 deletions(-)
> >
> > diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
> > index 5bc3ca0..7e6d821
> > --- a/arch/arm/mach-omap2/gpmc.c
> > +++ b/arch/arm/mach-omap2/gpmc.c
> > @@ -46,8 +46,9 @@
> > #define GPMC_ECC_CONFIG 0x1f4
> > #define GPMC_ECC_CONTROL 0x1f8
> > #define GPMC_ECC_SIZE_CONFIG 0x1fc
> > +#define GPMC_ECC1_RESULT 0x200
> >
> > -#define GPMC_CS0 0x60
> > +#define GPMC_CS0_BASE 0x60
> > #define GPMC_CS_SIZE 0x30
> >
> > #define GPMC_MEM_START 0x00000000
> > @@ -92,7 +93,9 @@ struct omap3_gpmc_regs {
> > static struct resource gpmc_mem_root;
> > static struct resource gpmc_cs_mem[GPMC_CS_NUM];
> > static DEFINE_SPINLOCK(gpmc_mem_lock);
> > -static unsigned gpmc_cs_map;
> > +static unsigned int gpmc_cs_map; /* flag for cs which are initialized */
> > +static int gpmc_pref_used = -EINVAL; /* cs using prefetch engine */
> > +static int gpmc_ecc_used = -EINVAL; /* cs using ecc engine */
> >
> > static void __iomem *gpmc_base;
> >
> > @@ -108,11 +111,27 @@ static u32 gpmc_read_reg(int idx)
> > return __raw_readl(gpmc_base + idx);
> > }
> >
> > +static void gpmc_cs_write_byte(int cs, int idx, u8 val)
> > +{
> > + void __iomem *reg_addr;
> > +
> > + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx;
> > + __raw_writeb(val, reg_addr);
> > +}
> > +
> > +static u8 gpmc_cs_read_byte(int cs, int idx)
> > +{
> > + void __iomem *reg_addr;
> > +
> > + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx;
> > + return __raw_readb(reg_addr);
> > +}
> > +
> > void gpmc_cs_write_reg(int cs, int idx, u32 val)
> > {
> > void __iomem *reg_addr;
> >
> > - reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx;
> > + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx;
> > __raw_writel(val, reg_addr);
> > }
> >
> > @@ -120,7 +139,7 @@ u32 gpmc_cs_read_reg(int cs, int idx)
> > {
> > void __iomem *reg_addr;
> >
> > - reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx;
> > + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx;
> > return __raw_readl(reg_addr);
> > }
> >
> > @@ -419,8 +438,100 @@ void gpmc_cs_free(int cs)
> > EXPORT_SYMBOL(gpmc_cs_free);
> >
> > /**
> > + * gpmc_hwcontrol - hardware specific access (read/ write) control
> > + * @cs: chip select number
> > + * @cmd: command type
> > + * @write: 1 for write; 0 for read
> > + * @wval: value to write
> > + * @rval: read pointer
> > + */
> > +int gpmc_hwcontrol(int cs, int cmd, int write, int wval, int *rval)
> > +{
> > + u32 regval = 0;
> > +
> > + if (!write && !rval)
> > + return -EINVAL;
> > +
> > + switch (cmd) {
> > + case GPMC_STATUS_BUFFER:
> > + regval = gpmc_read_reg(GPMC_STATUS);
> > + /* 1 : buffer is available to write */
> > + *rval = regval & GPMC_STATUS_BUFF_EMPTY;
> > + break;
> > +
> > + case GPMC_GET_SET_IRQ_STATUS:
> > + if (write)
> > + gpmc_write_reg(GPMC_IRQSTATUS, wval);
> > + else
> > + *rval = gpmc_read_reg(GPMC_IRQSTATUS);
> > + break;
> > +
> > + case GPMC_PREFETCH_FIFO_CNT:
> > + regval = gpmc_read_reg(GPMC_PREFETCH_STATUS);
> > + *rval = GPMC_PREFETCH_STATUS_FIFO_CNT(regval);
> > + break;
> > +
> > + case GPMC_PREFETCH_COUNT:
> > + regval = gpmc_read_reg(GPMC_PREFETCH_STATUS);
> > + *rval = GPMC_PREFETCH_STATUS_COUNT(regval);
> > + break;
> > +
> > + case GPMC_CONFIG_WP:
> > + regval = gpmc_read_reg(GPMC_CONFIG);
> > + if (wval)
> > + regval &= ~GPMC_CONFIG_WRITEPROTECT; /* WP is ON */
> > + else
> > + regval |= GPMC_CONFIG_WRITEPROTECT; /* WP is OFF */
> > + gpmc_write_reg(GPMC_CONFIG, regval);
> > + break;
> > +
> > + case GPMC_CONFIG_RDY_BSY:
> > + regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
> > + regval |= WR_RD_PIN_MONITORING;
> > + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
> > + break;
>
> IIRC, at least in OMAP2/3, ready/busy pin is not in use (not connected).
On the Logic LV SOM/Torpedo, indeed the R/B# pin from the NAND flash in
the Micron mt29c2g4maklajg-6it POP part is connected to the WAIT0 pin on
the OMAP3530 and I'm looking to use it to speed up NAND accesses.
> > +
> > + case GPMC_CONFIG_DEV_SIZE:
> > + regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
> > + regval |= GPMC_CONFIG1_DEVICESIZE(wval);
> > + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
> > + break;
> > +
> > + case GPMC_CONFIG_DEV_TYPE:
> > + regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
> > + regval |= GPMC_CONFIG1_DEVICETYPE(wval);
> > + if (wval == GPMC_DEVICETYPE_NOR)
> > + regval |= GPMC_CONFIG1_MUXADDDATA;
> > + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
> > + break;
> > +
> > + case GPMC_NAND_COMMAND:
> > + gpmc_cs_write_byte(cs, GPMC_CS_NAND_COMMAND, wval);
> > + break;
> > +
> > + case GPMC_NAND_ADDRESS:
> > + gpmc_cs_write_byte(cs, GPMC_CS_NAND_ADDRESS, wval);
> > + break;
> > +
> > + case GPMC_NAND_DATA:
> > + if (write)
> > + gpmc_cs_write_byte(cs, GPMC_CS_NAND_DATA, wval);
> > + else
> > + *rval = gpmc_cs_read_byte(cs, GPMC_CS_NAND_DATA);
> > + break;
> > +
> > + default:
> > + printk(KERN_ERR "gpmc_hwcontrol: Not supported\n");
> > + return -EINVAL;
> > + }
> > +
> > + return 0;
> > +}
> > +EXPORT_SYMBOL(gpmc_hwcontrol);
> > +
> > +/**
> > * gpmc_prefetch_enable - configures and starts prefetch transfer
> > - * @cs: nand cs (chip select) number
> > + * @cs: cs (chip select) number
> > * @dma_mode: dma mode enable (1) or disable (0)
> > * @u32_count: number of bytes to be transferred
> > * @is_write: prefetch read(0) or write post(1) mode
> > @@ -430,6 +541,11 @@ int gpmc_prefetch_enable(int cs, int dma_mode,
> > {
> > uint32_t prefetch_config1;
> >
> > + if (gpmc_pref_used == -EINVAL)
> > + gpmc_pref_used = cs;
> > + else
> > + return -EBUSY;
>
> This is not required. Prefetch engine has just one instance
>
> > +
> > if (!(gpmc_read_reg(GPMC_PREFETCH_CONTROL))) {
>
> and any prefetch request will be done only if above check passes.
> Which actually checks if 'prefetch' is busy or not.
> You can see in NAND driver (omap2.c) code, it understands that.
>
> > /* Set the amount of bytes to be prefetched */
> > gpmc_write_reg(GPMC_PREFETCH_CONFIG2, u32_count);
> > @@ -456,13 +572,20 @@ EXPORT_SYMBOL(gpmc_prefetch_enable);
> > /**
> > * gpmc_prefetch_reset - disables and stops the prefetch engine
> > */
> > -void gpmc_prefetch_reset(void)
> > +int gpmc_prefetch_reset(int cs)
> > {
> > + if (gpmc_pref_used == cs)
> > + gpmc_pref_used = -EINVAL;
> > + else
> > + return -EINVAL;
> > +
>
> This is also not required. As, this function will be called only if
> prefetch was used.
>
> > /* Stop the PFPW engine */
> > gpmc_write_reg(GPMC_PREFETCH_CONTROL, 0x0);
> >
> > /* Reset/disable the PFPW engine */
> > gpmc_write_reg(GPMC_PREFETCH_CONFIG1, 0x0);
> > +
> > + return 0;
> > }
> > EXPORT_SYMBOL(gpmc_prefetch_reset);
> >
> > @@ -615,3 +738,114 @@ void omap3_gpmc_restore_context(void)
> > }
> > }
> > #endif /* CONFIG_ARCH_OMAP3 */
> > +
> > +/**
> > + * gpmc_ecc_init - initialize hw ecc for device in GPMC controller
> > + * @cs: chip select number
> > + * @ecc_size: number of bytes for ecc generation
> > + */
> > +
> > +int gpmc_ecc_init(int cs, int ecc_size)
> > +{
> > + unsigned int val = 0x0;
> > +
> > + /* check if ecc engine already by another cs */
> > + if (gpmc_ecc_used == -EINVAL)
> > + gpmc_ecc_used = cs;
> > + else
> > + return -EBUSY;
> Here few things need be to consider:
> 1. 'init' is supposed to done once for every instance of driver during probe
> 2. But ECC engine, too, have only one instance at a time, So
> 3. As long as all NAND chip are supposed to use same ECC machenism, we
> can go for only one time 'init' for all drivers, perhaps in
> gpmc_nand.c.
> 4. But in case, different instances of driver (or NAND chip) requires
> different ECC machenism (for ex. Hamming or BCH, or even with
> different capabilities of error correction),
> this will no longer vailid. Then rather we should have something like
> 'gpmc_ecc_config' call to configer ECC engine for everytime a driver
> needs it (something like as it is done for prefetch engine).
>
> > +
> > + /* read ecc control register */
> > + val = gpmc_read_reg(GPMC_ECC_CONTROL);
> > +
> > + /* clear ecc and enable bits */
> > + val = ((0x00000001<<8) | 0x00000001);
> > + gpmc_write_reg(GPMC_ECC_CONTROL, val);
> > +
> > + /* Read from ECC Size Config Register */
> > + val = gpmc_read_reg(GPMC_ECC_SIZE_CONFIG);
> > +
> > + /* program ecc and result sizes */
> > + val = ((((ecc_size >> 1) - 1) << 22) | (0x0000000F));
> > + gpmc_write_reg(GPMC_ECC_SIZE_CONFIG, val);
> > +
> > + return 0;
> > +}
> > +
> > +/**
> > + * gpmc_calculate_ecc - generate non-inverted ecc bytes
> > + * @cs: chip select number
> > + * @dat: data pointer over which ecc is computed
> > + * @ecc_code: ecc code buffer
> > + *
> > + * Using non-inverted ECC is considered ugly since writing a blank
> > + * page (padding) will clear the ECC bytes. This is not a problem as long
> > + * no one is trying to write data on the seemingly unused page. Reading
> > + * an erased page will produce an ECC mismatch between generated and read
> > + * ECC bytes that has to be dealt with separately.
> > + */
> > +int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code)
> > +{
> > + unsigned int val = 0x0;
> > +
> > + if (gpmc_ecc_used != cs)
> > + return -EINVAL;
> > +
> > + /* read ecc result */
> > + val = gpmc_read_reg(GPMC_ECC1_RESULT);
> > + *ecc_code++ = val; /* P128e, ..., P1e */
> > + *ecc_code++ = val >> 16; /* P128o, ..., P1o */
> > + /* P2048o, P1024o, P512o, P256o, P2048e, P1024e, P512e, P256e */
> > + *ecc_code++ = ((val >> 8) & 0x0f) | ((val >> 20) & 0xf0);
> > +
> > + return 0;
> > +}
> > +
> > +/**
> > + * gpmc_enable_hwecc - enable hardware ecc functionality
> > + * @cs: chip select number
> > + * @mode: read/write mode
> > + * @dev_width: device bus width(1 for x16, 0 for x8)
> > + */
> > +int gpmc_enable_hwecc(int cs, int mode, int dev_width)
> > +{
> > + unsigned int val;
> > +
> > + if (gpmc_ecc_used != cs)
> > + return -EINVAL;
> > +
> > + switch (mode) {
> > + case GPMC_ECC_READ:
> > + gpmc_write_reg(GPMC_ECC_CONTROL, 0x101);
> > + break;
> > + case GPMC_ECC_READSYN:
> > + gpmc_write_reg(GPMC_ECC_CONTROL, 0x100);
> > + break;
> > + case GPMC_ECC_WRITE:
> > + gpmc_write_reg(GPMC_ECC_CONTROL, 0x101);
> > + break;
> > + default:
> > + printk(KERN_INFO "Error: Unrecognized Mode[%d]!\n", mode);
> > + break;
> > + }
> > +
> > + /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */
> > + val = (dev_width << 7) | (cs << 1) | (0x1);
> > + gpmc_write_reg(GPMC_ECC_CONFIG, val);
> > + return 0;
> > +}
> > +
> > +/**
> > + * gmpc_ecc_reset - release the HW ECC in GPMC controller
> > + * @cs: Chip select number
> > + */
> > +int gpmc_ecc_reset(int cs)
> > +{
> > + if (gpmc_ecc_used == cs)
> > + gpmc_ecc_used = -EINVAL;
> > + else
> > + return -EINVAL;
> > +
> > + return 0;
> > +}
> > +
> > diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h
> > index 145838a..67a3442
> > --- a/arch/arm/plat-omap/include/plat/gpmc.h
> > +++ b/arch/arm/plat-omap/include/plat/gpmc.h
> > @@ -27,8 +27,24 @@
> >
> > #define GPMC_CONFIG 0x50
> > #define GPMC_STATUS 0x54
> > -#define GPMC_CS0_BASE 0x60
> > -#define GPMC_CS_SIZE 0x30
> > +
> > +/* Control Commands */
> > +#define GPMC_CONFIG_WP 0x00000001
> > +#define GPMC_CONFIG_RDY_BSY 0x00000002
> > +#define GPMC_CONFIG_DEV_SIZE 0x00000003
> > +#define GPMC_CONFIG_DEV_TYPE 0x00000004
> > +#define GPMC_NAND_COMMAND 0x00000005
> > +#define GPMC_NAND_ADDRESS 0x00000006
> > +#define GPMC_NAND_DATA 0x00000007
> > +#define GPMC_STATUS_BUFFER 0x00000008 /* 1: buffer is available to write */
> > +#define GPMC_PREFETCH_FIFO_CNT 0x00000009 /* bytes available in FIFO for r/w */
> > +#define GPMC_PREFETCH_COUNT 0x0000000A /* remaining bytes to be read/write*/
> > +#define GPMC_GET_SET_IRQ_STATUS 0x0000000B
> > +
> > +/* ECC commands */
> > +#define GPMC_ECC_READ 0 /* Reset Hardware ECC for read */
> > +#define GPMC_ECC_WRITE 1 /* Reset Hardware ECC for write */
> > +#define GPMC_ECC_READSYN 2 /* Reset before syndrom is read back */
> >
> > #define GPMC_CONFIG1_WRAPBURST_SUPP (1 << 31)
> > #define GPMC_CONFIG1_READMULTIPLE_SUPP (1 << 30)
> > @@ -56,6 +72,14 @@
> > #define GPMC_CONFIG1_FCLK_DIV4 (GPMC_CONFIG1_FCLK_DIV(3))
> > #define GPMC_CONFIG7_CSVALID (1 << 6)
> >
> > +#define GPMC_DEVICETYPE_NOR 0
> > +#define GPMC_DEVICETYPE_NAND 2
> > +#define GPMC_CONFIG_WRITEPROTECT 0x00000010
> > +#define GPMC_STATUS_BUFF_EMPTY 0x00000001
> > +#define WR_RD_PIN_MONITORING 0x00600000
> > +#define GPMC_PREFETCH_STATUS_FIFO_CNT(val) ((val & 0x7f000000) >> 24)
> > +#define GPMC_PREFETCH_STATUS_COUNT(val) (val & 0x00003fff)
> > +
> > /*
> > * Note that all values in this struct are in nanoseconds, while
> > * the register values are in gpmc_fck cycles.
> > @@ -108,10 +132,15 @@ extern int gpmc_cs_set_reserved(int cs, int reserved);
> > extern int gpmc_cs_reserved(int cs);
> > extern int gpmc_prefetch_enable(int cs, int dma_mode,
> > unsigned int u32_count, int is_write);
> > -extern void gpmc_prefetch_reset(void);
> > +extern int gpmc_prefetch_reset(int cs);
> > extern int gpmc_prefetch_status(void);
> > extern void omap3_gpmc_save_context(void);
> > extern void omap3_gpmc_restore_context(void);
> > extern void gpmc_init(void);
> > +extern int gpmc_hwcontrol(int cs, int cmd, int write, int wval, int *rval);
> >
> > +int gpmc_ecc_init(int cs, int ecc_size);
> > +int gpmc_enable_hwecc(int cs, int mode, int dev_width);
> > +int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code);
> > +int gpmc_ecc_reset(int cs);
> > #endif
> > diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
> > index 7545568..206406b
> > --- a/drivers/mtd/nand/omap2.c
> > +++ b/drivers/mtd/nand/omap2.c
> > @@ -316,7 +316,7 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len)
> > } while (len);
> >
> > /* disable and stop the PFPW engine */
> > - gpmc_prefetch_reset();
> > + gpmc_prefetch_reset(info->gpmc_cs);
> Not required. see above comments.
>
> > }
> > }
> >
> > @@ -360,7 +360,7 @@ static void omap_write_buf_pref(struct mtd_info *mtd,
> > }
> >
> > /* disable and stop the PFPW engine */
> > - gpmc_prefetch_reset();
> > + gpmc_prefetch_reset(info->gpmc_cs);
> Not required. see above comments.
> > }
> > }
> >
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at http://vger.kernel.org/majordomo-info.html
> >
>
>
>
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply [flat|nested] 102+ messages in thread
* Re: [PATCH v3 2/3] omap3 nand: cleanup virtual address usages
2010-05-18 11:16 ` [PATCH v3 2/3] omap3 nand: cleanup virtual address usages Sukumar Ghorai
2010-05-18 11:16 ` [PATCH v3 3/3] omap3 nand: fix issue in board file to detect nand Sukumar Ghorai
@ 2010-05-19 15:30 ` Vimal Singh
2010-05-19 17:24 ` Ghorai, Sukumar
1 sibling, 1 reply; 102+ messages in thread
From: Vimal Singh @ 2010-05-19 15:30 UTC (permalink / raw)
To: Sukumar Ghorai
Cc: linux-omap, linux-mtd, tony, sakoman, mike, Artem.Bityutskiy
On Tue, May 18, 2010 at 4:46 PM, Sukumar Ghorai <s-ghorai@ti.com> wrote:
> This patch removes direct reference of gpmc address from generic nand platform code.
> Nand platform code now uses wrapper functions which are implemented in gpmc module.
>
> Signed-off-by: Sukumar Ghorai <s-ghorai@ti.com>
[...]
>
> @@ -287,16 +246,15 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len)
> {
> struct omap_nand_info *info = container_of(mtd,
> struct omap_nand_info, mtd);
> - uint32_t pfpw_status = 0, r_count = 0;
> + u32 r_count = 0;
> int ret = 0;
> - u32 *p = (u32 *)buf;
> + u32 *p;
>
> /* take care of subpage reads */
> for (; len % 4 != 0; ) {
> *buf++ = __raw_readb(info->nand.IO_ADDR_R);
> len--;
> }
> - p = (u32 *) buf;
Above code had an issue, which was fixed by this commit:
http://git.infradead.org/mtd-2.6.git/commitdiff/c3341d0ceb4de1680572024f50233403c6a8b10d
I would suggest you to prepare your patch on MTD tree.
>
> /* configure and start prefetch transfer */
> ret = gpmc_prefetch_enable(info->gpmc_cs, 0x0, len, 0x0);
> @@ -307,17 +265,18 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len)
> else
> omap_read_buf8(mtd, buf, len);
> } else {
> + p = (u32 *) buf;
> do {
> - pfpw_status = gpmc_prefetch_status();
> - r_count = ((pfpw_status >> 24) & 0x7F) >> 2;
> - ioread32_rep(info->nand_pref_fifo_add, p, r_count);
> + gpmc_hwcontrol(info->gpmc_cs,
> + GPMC_PREFETCH_FIFO_CNT, 0, 0, &r_count);
> + r_count = r_count >> 2;
> + ioread32_rep(info->nand.IO_ADDR_R, p, r_count);
> p += r_count;
> - len -= r_count << 2;
> + len -= (r_count << 2);
Braces are not required here.
> } while (len);
> -
After call to 'gpmc_prefetch_enable', next line are:
if (ret) {
/* PFPW engine is busy, use cpu copy method */
if (info->nand.options & NAND_BUSWIDTH_16)
...
...
> - /* disable and stop the PFPW engine */
> - gpmc_prefetch_reset(info->gpmc_cs);
> }
So, if above 'if' fails, driver will not get prefetch engine (it was
already busy). Then it doesn't makes sense to call for __reset__.
> + /* disable and stop the PFPW engine */
> + gpmc_prefetch_reset(info->gpmc_cs);
(Also see my comments on your other patch.)
> }
>
> /**
> @@ -331,13 +290,13 @@ static void omap_write_buf_pref(struct mtd_info *mtd,
> {
> struct omap_nand_info *info = container_of(mtd,
> struct omap_nand_info, mtd);
> - uint32_t pfpw_status = 0, w_count = 0;
> + uint32_t pref_count = 0, w_count = 0;
> int i = 0, ret = 0;
> - u16 *p = (u16 *) buf;
> + u16 *p;
>
> /* take care of subpage writes */
> if (len % 2 != 0) {
> - writeb(*buf, info->nand.IO_ADDR_R);
> + writeb(*buf, info->nand.IO_ADDR_W);
> p = (u16 *)(buf + 1);
> len--;
> }
> @@ -351,17 +310,22 @@ static void omap_write_buf_pref(struct mtd_info *mtd,
> else
> omap_write_buf8(mtd, buf, len);
> } else {
> - pfpw_status = gpmc_prefetch_status();
> - while (pfpw_status & 0x3FFF) {
> - w_count = ((pfpw_status >> 24) & 0x7F) >> 1;
> + p = (u16 *) buf;
> + while (len) {
> + gpmc_hwcontrol(info->gpmc_cs,
> + GPMC_PREFETCH_FIFO_CNT, 0, 0, &w_count);
> + w_count = w_count >> 1;
> for (i = 0; (i < w_count) && len; i++, len -= 2)
> - iowrite16(*p++, info->nand_pref_fifo_add);
> - pfpw_status = gpmc_prefetch_status();
> + iowrite16(*p++, info->nand.IO_ADDR_W);
> }
> -
> - /* disable and stop the PFPW engine */
> - gpmc_prefetch_reset(info->gpmc_cs);
> + /* wait for data to flushed-out before reset the prefetch */
> + do {
> + gpmc_hwcontrol(info->gpmc_cs,
> + GPMC_PREFETCH_COUNT, 0, 0, &pref_count);
> + } while (pref_count);
> }
> + /* disable and stop the PFPW engine */
> + gpmc_prefetch_reset(info->gpmc_cs);
Same as above.
> }
>
> #ifdef CONFIG_MTD_NAND_OMAP_PREFETCH_DMA
> @@ -448,8 +412,10 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr,
> /* setup and start DMA using dma_addr */
> wait_for_completion(&info->comp);
>
> - while (0x3fff & (prefetch_status = gpmc_prefetch_status()))
> - ;
> + do {
> + gpmc_hwcontrol(info->gpmc_cs,
> + GPMC_PREFETCH_COUNT, 0, 0, &prefetch_status);
> + } while (prefetch_status);
> /* disable and stop the PFPW engine */
> gpmc_prefetch_reset();
>
> @@ -502,7 +468,7 @@ static void omap_write_buf_dma_pref(struct mtd_info *mtd,
> omap_write_buf_pref(mtd, buf, len);
> else
> /* start transfer in DMA mode */
> - omap_nand_dma_transfer(mtd, buf, len, 0x1);
> + omap_nand_dma_transfer(mtd, (u_char *) buf, len, 0x1);
This is already fixed. See commit:
http://git.infradead.org/mtd-2.6.git/commitdiff/bdaefc41627b6f2815ef7aa476dfa4ebb3ad499f
Rest, patches looks good. It is a good clean-up all together.
--
Regards,
Vimal Singh
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 102+ messages in thread
* Re: [PATCH v3 1/3] omap3 gpmc: functionality enhancement
2010-05-19 14:46 ` [PATCH v3 1/3] omap3 gpmc: functionality enhancement Vimal Singh
2010-05-19 15:14 ` Peter Barada
@ 2010-05-19 15:48 ` Peter Barada
2010-05-19 18:04 ` Ghorai, Sukumar
1 sibling, 1 reply; 102+ messages in thread
From: Peter Barada @ 2010-05-19 15:48 UTC (permalink / raw)
To: Vimal Singh
Cc: Sukumar Ghorai, linux-omap, linux-mtd, tony, sakoman, mike,
Artem.Bityutskiy
On Wed, 2010-05-19 at 20:16 +0530, Vimal Singh wrote:
> On Tue, May 18, 2010 at 4:46 PM, Sukumar Ghorai <s-ghorai@ti.com> wrote:
> > few functions added in gpmc module and to be used by other drivers like NAND.
> > E.g.: - ioctl function
> > - ecc functions
> >
> > Signed-off-by: Sukumar Ghorai <s-ghorai@ti.com>
> > ---
> > arch/arm/mach-omap2/gpmc.c | 246 +++++++++++++++++++++++++++++++-
> > arch/arm/plat-omap/include/plat/gpmc.h | 35 ++++-
> > drivers/mtd/nand/omap2.c | 4 +-
> > 3 files changed, 274 insertions(+), 11 deletions(-)
> >
> > diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
> > index 5bc3ca0..7e6d821
> > --- a/arch/arm/mach-omap2/gpmc.c
> > +++ b/arch/arm/mach-omap2/gpmc.c
> > @@ -46,8 +46,9 @@
> > #define GPMC_ECC_CONFIG 0x1f4
> > #define GPMC_ECC_CONTROL 0x1f8
> > #define GPMC_ECC_SIZE_CONFIG 0x1fc
> > +#define GPMC_ECC1_RESULT 0x200
> >
> > -#define GPMC_CS0 0x60
> > +#define GPMC_CS0_BASE 0x60
> > #define GPMC_CS_SIZE 0x30
> >
> > #define GPMC_MEM_START 0x00000000
> > @@ -92,7 +93,9 @@ struct omap3_gpmc_regs {
> > static struct resource gpmc_mem_root;
> > static struct resource gpmc_cs_mem[GPMC_CS_NUM];
> > static DEFINE_SPINLOCK(gpmc_mem_lock);
> > -static unsigned gpmc_cs_map;
> > +static unsigned int gpmc_cs_map; /* flag for cs which are initialized */
> > +static int gpmc_pref_used = -EINVAL; /* cs using prefetch engine */
> > +static int gpmc_ecc_used = -EINVAL; /* cs using ecc engine */
> >
> > static void __iomem *gpmc_base;
> >
> > @@ -108,11 +111,27 @@ static u32 gpmc_read_reg(int idx)
> > return __raw_readl(gpmc_base + idx);
> > }
> >
> > +static void gpmc_cs_write_byte(int cs, int idx, u8 val)
> > +{
> > + void __iomem *reg_addr;
> > +
> > + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx;
> > + __raw_writeb(val, reg_addr);
> > +}
> > +
> > +static u8 gpmc_cs_read_byte(int cs, int idx)
> > +{
> > + void __iomem *reg_addr;
> > +
> > + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx;
> > + return __raw_readb(reg_addr);
> > +}
> > +
> > void gpmc_cs_write_reg(int cs, int idx, u32 val)
> > {
> > void __iomem *reg_addr;
> >
> > - reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx;
> > + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx;
> > __raw_writel(val, reg_addr);
> > }
> >
> > @@ -120,7 +139,7 @@ u32 gpmc_cs_read_reg(int cs, int idx)
> > {
> > void __iomem *reg_addr;
> >
> > - reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx;
> > + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx;
> > return __raw_readl(reg_addr);
> > }
> >
> > @@ -419,8 +438,100 @@ void gpmc_cs_free(int cs)
> > EXPORT_SYMBOL(gpmc_cs_free);
> >
> > /**
> > + * gpmc_hwcontrol - hardware specific access (read/ write) control
> > + * @cs: chip select number
> > + * @cmd: command type
> > + * @write: 1 for write; 0 for read
> > + * @wval: value to write
> > + * @rval: read pointer
> > + */
> > +int gpmc_hwcontrol(int cs, int cmd, int write, int wval, int *rval)
> > +{
> > + u32 regval = 0;
> > +
> > + if (!write && !rval)
> > + return -EINVAL;
> > +
> > + switch (cmd) {
> > + case GPMC_STATUS_BUFFER:
> > + regval = gpmc_read_reg(GPMC_STATUS);
> > + /* 1 : buffer is available to write */
> > + *rval = regval & GPMC_STATUS_BUFF_EMPTY;
> > + break;
> > +
> > + case GPMC_GET_SET_IRQ_STATUS:
> > + if (write)
> > + gpmc_write_reg(GPMC_IRQSTATUS, wval);
> > + else
> > + *rval = gpmc_read_reg(GPMC_IRQSTATUS);
> > + break;
> > +
> > + case GPMC_PREFETCH_FIFO_CNT:
> > + regval = gpmc_read_reg(GPMC_PREFETCH_STATUS);
> > + *rval = GPMC_PREFETCH_STATUS_FIFO_CNT(regval);
> > + break;
> > +
> > + case GPMC_PREFETCH_COUNT:
> > + regval = gpmc_read_reg(GPMC_PREFETCH_STATUS);
> > + *rval = GPMC_PREFETCH_STATUS_COUNT(regval);
> > + break;
> > +
> > + case GPMC_CONFIG_WP:
> > + regval = gpmc_read_reg(GPMC_CONFIG);
> > + if (wval)
> > + regval &= ~GPMC_CONFIG_WRITEPROTECT; /* WP is ON */
> > + else
> > + regval |= GPMC_CONFIG_WRITEPROTECT; /* WP is OFF */
> > + gpmc_write_reg(GPMC_CONFIG, regval);
> > + break;
> > +
> > + case GPMC_CONFIG_RDY_BSY:
> > + regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
> > + regval |= WR_RD_PIN_MONITORING;
> > + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
> > + break;
>
> IIRC, at least in OMAP2/3, ready/busy pin is not in use (not connected).
On the Logic OMAP3530 LV SOM and Torpedo modules, the R/B# pin of the
NAND in the Micron mt29c2g4maklajg-6it POP part is connected to the
WAIT0 pin on the OMAP3530 and I'm looking to use it to speed up NAND
accesses
> > +
> > + case GPMC_CONFIG_DEV_SIZE:
> > + regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
> > + regval |= GPMC_CONFIG1_DEVICESIZE(wval);
> > + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
> > + break;
> > +
> > + case GPMC_CONFIG_DEV_TYPE:
> > + regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
> > + regval |= GPMC_CONFIG1_DEVICETYPE(wval);
> > + if (wval == GPMC_DEVICETYPE_NOR)
> > + regval |= GPMC_CONFIG1_MUXADDDATA;
> > + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
> > + break;
> > +
> > + case GPMC_NAND_COMMAND:
> > + gpmc_cs_write_byte(cs, GPMC_CS_NAND_COMMAND, wval);
> > + break;
> > +
> > + case GPMC_NAND_ADDRESS:
> > + gpmc_cs_write_byte(cs, GPMC_CS_NAND_ADDRESS, wval);
> > + break;
> > +
> > + case GPMC_NAND_DATA:
> > + if (write)
> > + gpmc_cs_write_byte(cs, GPMC_CS_NAND_DATA, wval);
> > + else
> > + *rval = gpmc_cs_read_byte(cs, GPMC_CS_NAND_DATA);
> > + break;
> > +
> > + default:
> > + printk(KERN_ERR "gpmc_hwcontrol: Not supported\n");
> > + return -EINVAL;
> > + }
> > +
> > + return 0;
> > +}
> > +EXPORT_SYMBOL(gpmc_hwcontrol);
> > +
> > +/**
> > * gpmc_prefetch_enable - configures and starts prefetch transfer
> > - * @cs: nand cs (chip select) number
> > + * @cs: cs (chip select) number
> > * @dma_mode: dma mode enable (1) or disable (0)
> > * @u32_count: number of bytes to be transferred
> > * @is_write: prefetch read(0) or write post(1) mode
> > @@ -430,6 +541,11 @@ int gpmc_prefetch_enable(int cs, int dma_mode,
> > {
> > uint32_t prefetch_config1;
> >
> > + if (gpmc_pref_used == -EINVAL)
> > + gpmc_pref_used = cs;
> > + else
> > + return -EBUSY;
>
> This is not required. Prefetch engine has just one instance
>
> > +
> > if (!(gpmc_read_reg(GPMC_PREFETCH_CONTROL))) {
>
> and any prefetch request will be done only if above check passes.
> Which actually checks if 'prefetch' is busy or not.
> You can see in NAND driver (omap2.c) code, it understands that.
>
> > /* Set the amount of bytes to be prefetched */
> > gpmc_write_reg(GPMC_PREFETCH_CONFIG2, u32_count);
> > @@ -456,13 +572,20 @@ EXPORT_SYMBOL(gpmc_prefetch_enable);
> > /**
> > * gpmc_prefetch_reset - disables and stops the prefetch engine
> > */
> > -void gpmc_prefetch_reset(void)
> > +int gpmc_prefetch_reset(int cs)
> > {
> > + if (gpmc_pref_used == cs)
> > + gpmc_pref_used = -EINVAL;
> > + else
> > + return -EINVAL;
> > +
>
> This is also not required. As, this function will be called only if
> prefetch was used.
>
> > /* Stop the PFPW engine */
> > gpmc_write_reg(GPMC_PREFETCH_CONTROL, 0x0);
> >
> > /* Reset/disable the PFPW engine */
> > gpmc_write_reg(GPMC_PREFETCH_CONFIG1, 0x0);
> > +
> > + return 0;
> > }
> > EXPORT_SYMBOL(gpmc_prefetch_reset);
> >
> > @@ -615,3 +738,114 @@ void omap3_gpmc_restore_context(void)
> > }
> > }
> > #endif /* CONFIG_ARCH_OMAP3 */
> > +
> > +/**
> > + * gpmc_ecc_init - initialize hw ecc for device in GPMC controller
> > + * @cs: chip select number
> > + * @ecc_size: number of bytes for ecc generation
> > + */
> > +
> > +int gpmc_ecc_init(int cs, int ecc_size)
> > +{
> > + unsigned int val = 0x0;
> > +
> > + /* check if ecc engine already by another cs */
> > + if (gpmc_ecc_used == -EINVAL)
> > + gpmc_ecc_used = cs;
> > + else
> > + return -EBUSY;
> Here few things need be to consider:
> 1. 'init' is supposed to done once for every instance of driver during probe
> 2. But ECC engine, too, have only one instance at a time, So
> 3. As long as all NAND chip are supposed to use same ECC machenism, we
> can go for only one time 'init' for all drivers, perhaps in
> gpmc_nand.c.
> 4. But in case, different instances of driver (or NAND chip) requires
> different ECC machenism (for ex. Hamming or BCH, or even with
> different capabilities of error correction),
> this will no longer vailid. Then rather we should have something like
> 'gpmc_ecc_config' call to configer ECC engine for everytime a driver
> needs it (something like as it is done for prefetch engine).
>
> > +
> > + /* read ecc control register */
> > + val = gpmc_read_reg(GPMC_ECC_CONTROL);
> > +
> > + /* clear ecc and enable bits */
> > + val = ((0x00000001<<8) | 0x00000001);
> > + gpmc_write_reg(GPMC_ECC_CONTROL, val);
> > +
> > + /* Read from ECC Size Config Register */
> > + val = gpmc_read_reg(GPMC_ECC_SIZE_CONFIG);
> > +
> > + /* program ecc and result sizes */
> > + val = ((((ecc_size >> 1) - 1) << 22) | (0x0000000F));
> > + gpmc_write_reg(GPMC_ECC_SIZE_CONFIG, val);
> > +
> > + return 0;
> > +}
> > +
> > +/**
> > + * gpmc_calculate_ecc - generate non-inverted ecc bytes
> > + * @cs: chip select number
> > + * @dat: data pointer over which ecc is computed
> > + * @ecc_code: ecc code buffer
> > + *
> > + * Using non-inverted ECC is considered ugly since writing a blank
> > + * page (padding) will clear the ECC bytes. This is not a problem as long
> > + * no one is trying to write data on the seemingly unused page. Reading
> > + * an erased page will produce an ECC mismatch between generated and read
> > + * ECC bytes that has to be dealt with separately.
> > + */
> > +int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code)
> > +{
> > + unsigned int val = 0x0;
> > +
> > + if (gpmc_ecc_used != cs)
> > + return -EINVAL;
> > +
> > + /* read ecc result */
> > + val = gpmc_read_reg(GPMC_ECC1_RESULT);
> > + *ecc_code++ = val; /* P128e, ..., P1e */
> > + *ecc_code++ = val >> 16; /* P128o, ..., P1o */
> > + /* P2048o, P1024o, P512o, P256o, P2048e, P1024e, P512e, P256e */
> > + *ecc_code++ = ((val >> 8) & 0x0f) | ((val >> 20) & 0xf0);
> > +
> > + return 0;
> > +}
> > +
> > +/**
> > + * gpmc_enable_hwecc - enable hardware ecc functionality
> > + * @cs: chip select number
> > + * @mode: read/write mode
> > + * @dev_width: device bus width(1 for x16, 0 for x8)
> > + */
> > +int gpmc_enable_hwecc(int cs, int mode, int dev_width)
> > +{
> > + unsigned int val;
> > +
> > + if (gpmc_ecc_used != cs)
> > + return -EINVAL;
> > +
> > + switch (mode) {
> > + case GPMC_ECC_READ:
> > + gpmc_write_reg(GPMC_ECC_CONTROL, 0x101);
> > + break;
> > + case GPMC_ECC_READSYN:
> > + gpmc_write_reg(GPMC_ECC_CONTROL, 0x100);
> > + break;
> > + case GPMC_ECC_WRITE:
> > + gpmc_write_reg(GPMC_ECC_CONTROL, 0x101);
> > + break;
> > + default:
> > + printk(KERN_INFO "Error: Unrecognized Mode[%d]!\n", mode);
> > + break;
> > + }
> > +
> > + /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */
> > + val = (dev_width << 7) | (cs << 1) | (0x1);
> > + gpmc_write_reg(GPMC_ECC_CONFIG, val);
> > + return 0;
> > +}
> > +
> > +/**
> > + * gmpc_ecc_reset - release the HW ECC in GPMC controller
> > + * @cs: Chip select number
> > + */
> > +int gpmc_ecc_reset(int cs)
> > +{
> > + if (gpmc_ecc_used == cs)
> > + gpmc_ecc_used = -EINVAL;
> > + else
> > + return -EINVAL;
> > +
> > + return 0;
> > +}
> > +
> > diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h
> > index 145838a..67a3442
> > --- a/arch/arm/plat-omap/include/plat/gpmc.h
> > +++ b/arch/arm/plat-omap/include/plat/gpmc.h
> > @@ -27,8 +27,24 @@
> >
> > #define GPMC_CONFIG 0x50
> > #define GPMC_STATUS 0x54
> > -#define GPMC_CS0_BASE 0x60
> > -#define GPMC_CS_SIZE 0x30
> > +
> > +/* Control Commands */
> > +#define GPMC_CONFIG_WP 0x00000001
> > +#define GPMC_CONFIG_RDY_BSY 0x00000002
> > +#define GPMC_CONFIG_DEV_SIZE 0x00000003
> > +#define GPMC_CONFIG_DEV_TYPE 0x00000004
> > +#define GPMC_NAND_COMMAND 0x00000005
> > +#define GPMC_NAND_ADDRESS 0x00000006
> > +#define GPMC_NAND_DATA 0x00000007
> > +#define GPMC_STATUS_BUFFER 0x00000008 /* 1: buffer is available to write */
> > +#define GPMC_PREFETCH_FIFO_CNT 0x00000009 /* bytes available in FIFO for r/w */
> > +#define GPMC_PREFETCH_COUNT 0x0000000A /* remaining bytes to be read/write*/
> > +#define GPMC_GET_SET_IRQ_STATUS 0x0000000B
> > +
> > +/* ECC commands */
> > +#define GPMC_ECC_READ 0 /* Reset Hardware ECC for read */
> > +#define GPMC_ECC_WRITE 1 /* Reset Hardware ECC for write */
> > +#define GPMC_ECC_READSYN 2 /* Reset before syndrom is read back */
> >
> > #define GPMC_CONFIG1_WRAPBURST_SUPP (1 << 31)
> > #define GPMC_CONFIG1_READMULTIPLE_SUPP (1 << 30)
> > @@ -56,6 +72,14 @@
> > #define GPMC_CONFIG1_FCLK_DIV4 (GPMC_CONFIG1_FCLK_DIV(3))
> > #define GPMC_CONFIG7_CSVALID (1 << 6)
> >
> > +#define GPMC_DEVICETYPE_NOR 0
> > +#define GPMC_DEVICETYPE_NAND 2
> > +#define GPMC_CONFIG_WRITEPROTECT 0x00000010
> > +#define GPMC_STATUS_BUFF_EMPTY 0x00000001
> > +#define WR_RD_PIN_MONITORING 0x00600000
> > +#define GPMC_PREFETCH_STATUS_FIFO_CNT(val) ((val & 0x7f000000) >> 24)
> > +#define GPMC_PREFETCH_STATUS_COUNT(val) (val & 0x00003fff)
> > +
> > /*
> > * Note that all values in this struct are in nanoseconds, while
> > * the register values are in gpmc_fck cycles.
> > @@ -108,10 +132,15 @@ extern int gpmc_cs_set_reserved(int cs, int reserved);
> > extern int gpmc_cs_reserved(int cs);
> > extern int gpmc_prefetch_enable(int cs, int dma_mode,
> > unsigned int u32_count, int is_write);
> > -extern void gpmc_prefetch_reset(void);
> > +extern int gpmc_prefetch_reset(int cs);
> > extern int gpmc_prefetch_status(void);
> > extern void omap3_gpmc_save_context(void);
> > extern void omap3_gpmc_restore_context(void);
> > extern void gpmc_init(void);
> > +extern int gpmc_hwcontrol(int cs, int cmd, int write, int wval, int *rval);
> >
> > +int gpmc_ecc_init(int cs, int ecc_size);
> > +int gpmc_enable_hwecc(int cs, int mode, int dev_width);
> > +int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code);
> > +int gpmc_ecc_reset(int cs);
> > #endif
> > diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
> > index 7545568..206406b
> > --- a/drivers/mtd/nand/omap2.c
> > +++ b/drivers/mtd/nand/omap2.c
> > @@ -316,7 +316,7 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len)
> > } while (len);
> >
> > /* disable and stop the PFPW engine */
> > - gpmc_prefetch_reset();
> > + gpmc_prefetch_reset(info->gpmc_cs);
> Not required. see above comments.
>
> > }
> > }
> >
> > @@ -360,7 +360,7 @@ static void omap_write_buf_pref(struct mtd_info *mtd,
> > }
> >
> > /* disable and stop the PFPW engine */
> > - gpmc_prefetch_reset();
> > + gpmc_prefetch_reset(info->gpmc_cs);
> Not required. see above comments.
> > }
> > }
> >
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at http://vger.kernel.org/majordomo-info.html
> >
>
>
>
^ permalink raw reply [flat|nested] 102+ messages in thread
* RE: [PATCH v3 2/3] omap3 nand: cleanup virtual address usages
2010-05-19 15:30 ` [PATCH v3 2/3] omap3 nand: cleanup virtual address usages Vimal Singh
@ 2010-05-19 17:24 ` Ghorai, Sukumar
2010-05-19 18:07 ` Vimal Singh
0 siblings, 1 reply; 102+ messages in thread
From: Ghorai, Sukumar @ 2010-05-19 17:24 UTC (permalink / raw)
To: Vimal Singh
Cc: linux-omap@vger.kernel.org, linux-mtd@lists.infradead.org,
tony@atomide.com, sakoman@gmail.com, mike@compulab.co.il,
Artem.Bityutskiy@nokia.com
Vimal,
> -----Original Message-----
> From: Vimal Singh [mailto:vimal.newwork@gmail.com]
> Sent: 2010-05-19 21:00
> To: Ghorai, Sukumar
> Cc: linux-omap@vger.kernel.org; linux-mtd@lists.infradead.org;
> tony@atomide.com; sakoman@gmail.com; mike@compulab.co.il;
> Artem.Bityutskiy@nokia.com
> Subject: Re: [PATCH v3 2/3] omap3 nand: cleanup virtual address usages
>
> On Tue, May 18, 2010 at 4:46 PM, Sukumar Ghorai <s-ghorai@ti.com> wrote:
> > This patch removes direct reference of gpmc address from generic nand
> platform code.
> > Nand platform code now uses wrapper functions which are implemented in
> gpmc module.
> >
> > Signed-off-by: Sukumar Ghorai <s-ghorai@ti.com>
> [...]
>
> >
> > @@ -287,16 +246,15 @@ static void omap_read_buf_pref(struct mtd_info
> *mtd, u_char *buf, int len)
> > {
> > struct omap_nand_info *info = container_of(mtd,
> > struct omap_nand_info,
> mtd);
> > - uint32_t pfpw_status = 0, r_count = 0;
> > + u32 r_count = 0;
> > int ret = 0;
> > - u32 *p = (u32 *)buf;
> > + u32 *p;
> >
> > /* take care of subpage reads */
> > for (; len % 4 != 0; ) {
> > *buf++ = __raw_readb(info->nand.IO_ADDR_R);
> > len--;
> > }
> > - p = (u32 *) buf;
>
> Above code had an issue, which was fixed by this commit:
> http://git.infradead.org/mtd-
> 2.6.git/commitdiff/c3341d0ceb4de1680572024f50233403c6a8b10d
>
> I would suggest you to prepare your patch on MTD tree.
[Ghorai] Patches started posting on lo. And lets continue the same.
>
> >
> > /* configure and start prefetch transfer */
> > ret = gpmc_prefetch_enable(info->gpmc_cs, 0x0, len, 0x0);
> > @@ -307,17 +265,18 @@ static void omap_read_buf_pref(struct mtd_info
> *mtd, u_char *buf, int len)
> > else
> > omap_read_buf8(mtd, buf, len);
> > } else {
> > + p = (u32 *) buf;
> > do {
> > - pfpw_status = gpmc_prefetch_status();
> > - r_count = ((pfpw_status >> 24) & 0x7F) >> 2;
> > - ioread32_rep(info->nand_pref_fifo_add, p,
> r_count);
> > + gpmc_hwcontrol(info->gpmc_cs,
> > + GPMC_PREFETCH_FIFO_CNT, 0, 0, &r_count);
> > + r_count = r_count >> 2;
> > + ioread32_rep(info->nand.IO_ADDR_R, p, r_count);
> > p += r_count;
> > - len -= r_count << 2;
> > + len -= (r_count << 2);
>
> Braces are not required here.
[Ghorai] thanks
>
> > } while (len);
> > -
>
> After call to 'gpmc_prefetch_enable', next line are:
> if (ret) {
> /* PFPW engine is busy, use cpu copy method */
> if (info->nand.options & NAND_BUSWIDTH_16)
> ...
> ...
> > - /* disable and stop the PFPW engine */
> > - gpmc_prefetch_reset(info->gpmc_cs);
> > }
>
> So, if above 'if' fails, driver will not get prefetch engine (it was
> already busy). Then it doesn't makes sense to call for __reset__.
[Ghorai] I will take this clean up as 4th patch. As its not matching with patch description.
>
> > + /* disable and stop the PFPW engine */
> > + gpmc_prefetch_reset(info->gpmc_cs);
>
> (Also see my comments on your other patch.)
[Ghorai] Agree and I will take this kind of cleanup as 4th patch
>
> > }
> >
> > /**
> > @@ -331,13 +290,13 @@ static void omap_write_buf_pref(struct mtd_info
> *mtd,
> > {
> > struct omap_nand_info *info = container_of(mtd,
> > struct omap_nand_info,
> mtd);
> > - uint32_t pfpw_status = 0, w_count = 0;
> > + uint32_t pref_count = 0, w_count = 0;
> > int i = 0, ret = 0;
> > - u16 *p = (u16 *) buf;
> > + u16 *p;
> >
> > /* take care of subpage writes */
> > if (len % 2 != 0) {
> > - writeb(*buf, info->nand.IO_ADDR_R);
> > + writeb(*buf, info->nand.IO_ADDR_W);
> > p = (u16 *)(buf + 1);
> > len--;
> > }
> > @@ -351,17 +310,22 @@ static void omap_write_buf_pref(struct mtd_info
> *mtd,
> > else
> > omap_write_buf8(mtd, buf, len);
> > } else {
> > - pfpw_status = gpmc_prefetch_status();
> > - while (pfpw_status & 0x3FFF) {
> > - w_count = ((pfpw_status >> 24) & 0x7F) >> 1;
> > + p = (u16 *) buf;
> > + while (len) {
> > + gpmc_hwcontrol(info->gpmc_cs,
> > + GPMC_PREFETCH_FIFO_CNT, 0, 0,
> &w_count);
> > + w_count = w_count >> 1;
> > for (i = 0; (i < w_count) && len; i++, len -= 2)
> > - iowrite16(*p++, info-
> >nand_pref_fifo_add);
> > - pfpw_status = gpmc_prefetch_status();
> > + iowrite16(*p++, info->nand.IO_ADDR_W);
> > }
> > -
> > - /* disable and stop the PFPW engine */
> > - gpmc_prefetch_reset(info->gpmc_cs);
> > + /* wait for data to flushed-out before reset the
> prefetch */
> > + do {
> > + gpmc_hwcontrol(info->gpmc_cs,
> > + GPMC_PREFETCH_COUNT, 0, 0, &pref_count);
> > + } while (pref_count);
> > }
> > + /* disable and stop the PFPW engine */
> > + gpmc_prefetch_reset(info->gpmc_cs);
>
> Same as above.
[Ghorai] Agree and I will take this kind of cleanup as 4th patch, as its not matching with patch description.
>
>
> > }
> >
> > #ifdef CONFIG_MTD_NAND_OMAP_PREFETCH_DMA
> > @@ -448,8 +412,10 @@ static inline int omap_nand_dma_transfer(struct
> mtd_info *mtd, void *addr,
> > /* setup and start DMA using dma_addr */
> > wait_for_completion(&info->comp);
> >
> > - while (0x3fff & (prefetch_status = gpmc_prefetch_status()))
> > - ;
> > + do {
> > + gpmc_hwcontrol(info->gpmc_cs,
> > + GPMC_PREFETCH_COUNT, 0, 0,
> &prefetch_status);
> > + } while (prefetch_status);
> > /* disable and stop the PFPW engine */
> > gpmc_prefetch_reset();
> >
> > @@ -502,7 +468,7 @@ static void omap_write_buf_dma_pref(struct mtd_info
> *mtd,
> > omap_write_buf_pref(mtd, buf, len);
> > else
> > /* start transfer in DMA mode */
> > - omap_nand_dma_transfer(mtd, buf, len, 0x1);
> > + omap_nand_dma_transfer(mtd, (u_char *) buf, len, 0x1);
>
> This is already fixed. See commit:
> http://git.infradead.org/mtd-
> 2.6.git/commitdiff/bdaefc41627b6f2815ef7aa476dfa4ebb3ad499f
[Ghorai] thanks I will omit this from this patch
>
>
> Rest, patches looks good. It is a good clean-up all together.
[Ghorai] Is it possible for you to check once again if you have any additional comments! This is to identify the issue if any at early stage.
>
> --
> Regards,
> Vimal Singh
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 102+ messages in thread
* RE: [PATCH v3 1/3] omap3 gpmc: functionality enhancement
2010-05-19 15:48 ` Peter Barada
@ 2010-05-19 18:04 ` Ghorai, Sukumar
2010-05-19 18:30 ` Vimal Singh
0 siblings, 1 reply; 102+ messages in thread
From: Ghorai, Sukumar @ 2010-05-19 18:04 UTC (permalink / raw)
To: Vimal Singh
Cc: linux-omap@vger.kernel.org, linux-mtd@lists.infradead.org,
tony@atomide.com, sakoman@gmail.com, mike@compulab.co.il,
Artem.Bityutskiy@nokia.com, peter.barada@gmail.com
Vimal,
> -----Original Message-----
> From: Peter Barada [mailto:peter.barada@gmail.com]
> Sent: 2010-05-19 21:18
> To: Vimal Singh
> Cc: Ghorai, Sukumar; linux-omap@vger.kernel.org; linux-
> mtd@lists.infradead.org; tony@atomide.com; sakoman@gmail.com;
> mike@compulab.co.il; Artem.Bityutskiy@nokia.com
> Subject: Re: [PATCH v3 1/3] omap3 gpmc: functionality enhancement
>
> On Wed, 2010-05-19 at 20:16 +0530, Vimal Singh wrote:
> > On Tue, May 18, 2010 at 4:46 PM, Sukumar Ghorai <s-ghorai@ti.com> wrote:
> > > few functions added in gpmc module and to be used by other drivers
> like NAND.
> > > E.g.: - ioctl function
> > > - ecc functions
> > >
> > > Signed-off-by: Sukumar Ghorai <s-ghorai@ti.com>
> > > ---
> > > arch/arm/mach-omap2/gpmc.c | 246
> +++++++++++++++++++++++++++++++-
> > > arch/arm/plat-omap/include/plat/gpmc.h | 35 ++++-
> > > drivers/mtd/nand/omap2.c | 4 +-
> > > 3 files changed, 274 insertions(+), 11 deletions(-)
> > >
> > > diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
> > > index 5bc3ca0..7e6d821
> > > --- a/arch/arm/mach-omap2/gpmc.c
> > > +++ b/arch/arm/mach-omap2/gpmc.c
> > > @@ -46,8 +46,9 @@
> > > #define GPMC_ECC_CONFIG 0x1f4
> > > #define GPMC_ECC_CONTROL 0x1f8
> > > #define GPMC_ECC_SIZE_CONFIG 0x1fc
> > > +#define GPMC_ECC1_RESULT 0x200
> > >
> > > -#define GPMC_CS0 0x60
> > > +#define GPMC_CS0_BASE 0x60
> > > #define GPMC_CS_SIZE 0x30
> > >
> > > #define GPMC_MEM_START 0x00000000
> > > @@ -92,7 +93,9 @@ struct omap3_gpmc_regs {
> > > static struct resource gpmc_mem_root;
> > > static struct resource gpmc_cs_mem[GPMC_CS_NUM];
> > > static DEFINE_SPINLOCK(gpmc_mem_lock);
> > > -static unsigned gpmc_cs_map;
> > > +static unsigned int gpmc_cs_map; /* flag for cs which
> are initialized */
> > > +static int gpmc_pref_used = -EINVAL; /* cs using prefetch engine */
> > > +static int gpmc_ecc_used = -EINVAL; /* cs using ecc engine */
> > >
> > > static void __iomem *gpmc_base;
> > >
> > > @@ -108,11 +111,27 @@ static u32 gpmc_read_reg(int idx)
> > > return __raw_readl(gpmc_base + idx);
> > > }
> > >
> > > +static void gpmc_cs_write_byte(int cs, int idx, u8 val)
> > > +{
> > > + void __iomem *reg_addr;
> > > +
> > > + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) +
> idx;
> > > + __raw_writeb(val, reg_addr);
> > > +}
> > > +
> > > +static u8 gpmc_cs_read_byte(int cs, int idx)
> > > +{
> > > + void __iomem *reg_addr;
> > > +
> > > + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) +
> idx;
> > > + return __raw_readb(reg_addr);
> > > +}
> > > +
> > > void gpmc_cs_write_reg(int cs, int idx, u32 val)
> > > {
> > > void __iomem *reg_addr;
> > >
> > > - reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx;
> > > + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) +
> idx;
> > > __raw_writel(val, reg_addr);
> > > }
> > >
> > > @@ -120,7 +139,7 @@ u32 gpmc_cs_read_reg(int cs, int idx)
> > > {
> > > void __iomem *reg_addr;
> > >
> > > - reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx;
> > > + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) +
> idx;
> > > return __raw_readl(reg_addr);
> > > }
> > >
> > > @@ -419,8 +438,100 @@ void gpmc_cs_free(int cs)
> > > EXPORT_SYMBOL(gpmc_cs_free);
> > >
> > > /**
> > > + * gpmc_hwcontrol - hardware specific access (read/ write) control
> > > + * @cs: chip select number
> > > + * @cmd: command type
> > > + * @write: 1 for write; 0 for read
> > > + * @wval: value to write
> > > + * @rval: read pointer
> > > + */
> > > +int gpmc_hwcontrol(int cs, int cmd, int write, int wval, int *rval)
> > > +{
> > > + u32 regval = 0;
> > > +
> > > + if (!write && !rval)
> > > + return -EINVAL;
> > > +
> > > + switch (cmd) {
> > > + case GPMC_STATUS_BUFFER:
> > > + regval = gpmc_read_reg(GPMC_STATUS);
> > > + /* 1 : buffer is available to write */
> > > + *rval = regval & GPMC_STATUS_BUFF_EMPTY;
> > > + break;
> > > +
> > > + case GPMC_GET_SET_IRQ_STATUS:
> > > + if (write)
> > > + gpmc_write_reg(GPMC_IRQSTATUS, wval);
> > > + else
> > > + *rval = gpmc_read_reg(GPMC_IRQSTATUS);
> > > + break;
> > > +
> > > + case GPMC_PREFETCH_FIFO_CNT:
> > > + regval = gpmc_read_reg(GPMC_PREFETCH_STATUS);
> > > + *rval = GPMC_PREFETCH_STATUS_FIFO_CNT(regval);
> > > + break;
> > > +
> > > + case GPMC_PREFETCH_COUNT:
> > > + regval = gpmc_read_reg(GPMC_PREFETCH_STATUS);
> > > + *rval = GPMC_PREFETCH_STATUS_COUNT(regval);
> > > + break;
> > > +
> > > + case GPMC_CONFIG_WP:
> > > + regval = gpmc_read_reg(GPMC_CONFIG);
> > > + if (wval)
> > > + regval &= ~GPMC_CONFIG_WRITEPROTECT; /* WP is
> ON */
> > > + else
> > > + regval |= GPMC_CONFIG_WRITEPROTECT; /* WP is
> OFF */
> > > + gpmc_write_reg(GPMC_CONFIG, regval);
> > > + break;
> > > +
> > > + case GPMC_CONFIG_RDY_BSY:
> > > + regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
> > > + regval |= WR_RD_PIN_MONITORING;
> > > + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
> > > + break;
> >
> > IIRC, at least in OMAP2/3, ready/busy pin is not in use (not connected).
>
> On the Logic OMAP3530 LV SOM and Torpedo modules, the R/B# pin of the
> NAND in the Micron mt29c2g4maklajg-6it POP part is connected to the
> WAIT0 pin on the OMAP3530 and I'm looking to use it to speed up NAND
> accesses
[Ghorai] So better keep this feature,
>
> > > +
> > > + case GPMC_CONFIG_DEV_SIZE:
> > > + regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
> > > + regval |= GPMC_CONFIG1_DEVICESIZE(wval);
> > > + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
> > > + break;
> > > +
> > > + case GPMC_CONFIG_DEV_TYPE:
> > > + regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
> > > + regval |= GPMC_CONFIG1_DEVICETYPE(wval);
> > > + if (wval == GPMC_DEVICETYPE_NOR)
> > > + regval |= GPMC_CONFIG1_MUXADDDATA;
> > > + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
> > > + break;
> > > +
> > > + case GPMC_NAND_COMMAND:
> > > + gpmc_cs_write_byte(cs, GPMC_CS_NAND_COMMAND, wval);
> > > + break;
> > > +
> > > + case GPMC_NAND_ADDRESS:
> > > + gpmc_cs_write_byte(cs, GPMC_CS_NAND_ADDRESS, wval);
> > > + break;
> > > +
> > > + case GPMC_NAND_DATA:
> > > + if (write)
> > > + gpmc_cs_write_byte(cs, GPMC_CS_NAND_DATA,
> wval);
> > > + else
> > > + *rval = gpmc_cs_read_byte(cs,
> GPMC_CS_NAND_DATA);
> > > + break;
> > > +
> > > + default:
> > > + printk(KERN_ERR "gpmc_hwcontrol: Not supported\n");
> > > + return -EINVAL;
> > > + }
> > > +
> > > + return 0;
> > > +}
> > > +EXPORT_SYMBOL(gpmc_hwcontrol);
> > > +
> > > +/**
> > > * gpmc_prefetch_enable - configures and starts prefetch transfer
> > > - * @cs: nand cs (chip select) number
> > > + * @cs: cs (chip select) number
> > > * @dma_mode: dma mode enable (1) or disable (0)
> > > * @u32_count: number of bytes to be transferred
> > > * @is_write: prefetch read(0) or write post(1) mode
> > > @@ -430,6 +541,11 @@ int gpmc_prefetch_enable(int cs, int dma_mode,
> > > {
> > > uint32_t prefetch_config1;
> > >
> > > + if (gpmc_pref_used == -EINVAL)
> > > + gpmc_pref_used = cs;
> > > + else
> > > + return -EBUSY;
> >
> > This is not required. Prefetch engine has just one instance
> >
> > > +
> > > if (!(gpmc_read_reg(GPMC_PREFETCH_CONTROL))) {
> >
> > and any prefetch request will be done only if above check passes.
> > Which actually checks if 'prefetch' is busy or not.
> > You can see in NAND driver (omap2.c) code, it understands that.
[Ghorai] Agree here and also you mentioned not to use the reset function. So will take all these as 4th patch for cleanup.
> >
> > > /* Set the amount of bytes to be prefetched */
> > > gpmc_write_reg(GPMC_PREFETCH_CONFIG2, u32_count);
> > > @@ -456,13 +572,20 @@ EXPORT_SYMBOL(gpmc_prefetch_enable);
> > > /**
> > > * gpmc_prefetch_reset - disables and stops the prefetch engine
> > > */
> > > -void gpmc_prefetch_reset(void)
> > > +int gpmc_prefetch_reset(int cs)
> > > {
> > > + if (gpmc_pref_used == cs)
> > > + gpmc_pref_used = -EINVAL;
> > > + else
> > > + return -EINVAL;
> > > +
> >
> > This is also not required. As, this function will be called only if
> > prefetch was used.
[Ghorai] Agree. Can you see this input too?
http://www.mail-archive.com/linux-omap@vger.kernel.org/msg28520.html
> >
> > > /* Stop the PFPW engine */
> > > gpmc_write_reg(GPMC_PREFETCH_CONTROL, 0x0);
> > >
> > > /* Reset/disable the PFPW engine */
> > > gpmc_write_reg(GPMC_PREFETCH_CONFIG1, 0x0);
> > > +
> > > + return 0;
> > > }
> > > EXPORT_SYMBOL(gpmc_prefetch_reset);
> > >
> > > @@ -615,3 +738,114 @@ void omap3_gpmc_restore_context(void)
> > > }
> > > }
> > > #endif /* CONFIG_ARCH_OMAP3 */
> > > +
> > > +/**
> > > + * gpmc_ecc_init - initialize hw ecc for device in GPMC controller
> > > + * @cs: chip select number
> > > + * @ecc_size: number of bytes for ecc generation
> > > + */
> > > +
> > > +int gpmc_ecc_init(int cs, int ecc_size)
> > > +{
> > > + unsigned int val = 0x0;
> > > +
> > > + /* check if ecc engine already by another cs */
> > > + if (gpmc_ecc_used == -EINVAL)
> > > + gpmc_ecc_used = cs;
> > > + else
> > > + return -EBUSY;
> > Here few things need be to consider:
> > 1. 'init' is supposed to done once for every instance of driver during
> probe
> > 2. But ECC engine, too, have only one instance at a time, So
> > 3. As long as all NAND chip are supposed to use same ECC machenism, we
> > can go for only one time 'init' for all drivers, perhaps in
> > gpmc_nand.c.
> > 4. But in case, different instances of driver (or NAND chip) requires
> > different ECC machenism (for ex. Hamming or BCH, or even with
> > different capabilities of error correction),
> > this will no longer vailid. Then rather we should have something like
> > 'gpmc_ecc_config' call to configer ECC engine for everytime a driver
> > needs it (something like as it is done for prefetch engine).
[Ghorai]
a. do you think it will reduce the throughput?
b. Moreover I think we will take this as 5th patch as cleanup/ improvemnt.
c. And how to know that ECC engine is in used other driver should not use it? Any bit to know that ecc engine is busy, as we check for prefetch?
d. any further input on http://www.mail-archive.com/linux-omap@vger.kernel.org/msg28520.html
> >
> > > +
> > > + /* read ecc control register */
> > > + val = gpmc_read_reg(GPMC_ECC_CONTROL);
> > > +
> > > + /* clear ecc and enable bits */
> > > + val = ((0x00000001<<8) | 0x00000001);
> > > + gpmc_write_reg(GPMC_ECC_CONTROL, val);
> > > +
> > > + /* Read from ECC Size Config Register */
> > > + val = gpmc_read_reg(GPMC_ECC_SIZE_CONFIG);
> > > +
> > > + /* program ecc and result sizes */
> > > + val = ((((ecc_size >> 1) - 1) << 22) | (0x0000000F));
> > > + gpmc_write_reg(GPMC_ECC_SIZE_CONFIG, val);
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +/**
> > > + * gpmc_calculate_ecc - generate non-inverted ecc bytes
> > > + * @cs: chip select number
> > > + * @dat: data pointer over which ecc is computed
> > > + * @ecc_code: ecc code buffer
> > > + *
> > > + * Using non-inverted ECC is considered ugly since writing a blank
> > > + * page (padding) will clear the ECC bytes. This is not a problem as
> long
> > > + * no one is trying to write data on the seemingly unused page.
> Reading
> > > + * an erased page will produce an ECC mismatch between generated and
> read
> > > + * ECC bytes that has to be dealt with separately.
> > > + */
> > > +int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code)
> > > +{
> > > + unsigned int val = 0x0;
> > > +
> > > + if (gpmc_ecc_used != cs)
> > > + return -EINVAL;
> > > +
> > > + /* read ecc result */
> > > + val = gpmc_read_reg(GPMC_ECC1_RESULT);
> > > + *ecc_code++ = val; /* P128e, ..., P1e */
> > > + *ecc_code++ = val >> 16; /* P128o, ..., P1o */
> > > + /* P2048o, P1024o, P512o, P256o, P2048e, P1024e, P512e, P256e
> */
> > > + *ecc_code++ = ((val >> 8) & 0x0f) | ((val >> 20) & 0xf0);
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +/**
> > > + * gpmc_enable_hwecc - enable hardware ecc functionality
> > > + * @cs: chip select number
> > > + * @mode: read/write mode
> > > + * @dev_width: device bus width(1 for x16, 0 for x8)
> > > + */
> > > +int gpmc_enable_hwecc(int cs, int mode, int dev_width)
> > > +{
> > > + unsigned int val;
> > > +
> > > + if (gpmc_ecc_used != cs)
> > > + return -EINVAL;
> > > +
> > > + switch (mode) {
> > > + case GPMC_ECC_READ:
> > > + gpmc_write_reg(GPMC_ECC_CONTROL, 0x101);
> > > + break;
> > > + case GPMC_ECC_READSYN:
> > > + gpmc_write_reg(GPMC_ECC_CONTROL, 0x100);
> > > + break;
> > > + case GPMC_ECC_WRITE:
> > > + gpmc_write_reg(GPMC_ECC_CONTROL, 0x101);
> > > + break;
> > > + default:
> > > + printk(KERN_INFO "Error: Unrecognized Mode[%d]!\n",
> mode);
> > > + break;
> > > + }
> > > +
> > > + /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */
> > > + val = (dev_width << 7) | (cs << 1) | (0x1);
> > > + gpmc_write_reg(GPMC_ECC_CONFIG, val);
> > > + return 0;
> > > +}
> > > +
> > > +/**
> > > + * gmpc_ecc_reset - release the HW ECC in GPMC controller
> > > + * @cs: Chip select number
> > > + */
> > > +int gpmc_ecc_reset(int cs)
> > > +{
> > > + if (gpmc_ecc_used == cs)
> > > + gpmc_ecc_used = -EINVAL;
> > > + else
> > > + return -EINVAL;
> > > +
> > > + return 0;
> > > +}
> > > +
> > > diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-
> omap/include/plat/gpmc.h
> > > index 145838a..67a3442
> > > --- a/arch/arm/plat-omap/include/plat/gpmc.h
> > > +++ b/arch/arm/plat-omap/include/plat/gpmc.h
> > > @@ -27,8 +27,24 @@
> > >
> > > #define GPMC_CONFIG 0x50
> > > #define GPMC_STATUS 0x54
> > > -#define GPMC_CS0_BASE 0x60
> > > -#define GPMC_CS_SIZE 0x30
> > > +
> > > +/* Control Commands */
> > > +#define GPMC_CONFIG_WP 0x00000001
> > > +#define GPMC_CONFIG_RDY_BSY 0x00000002
> > > +#define GPMC_CONFIG_DEV_SIZE 0x00000003
> > > +#define GPMC_CONFIG_DEV_TYPE 0x00000004
> > > +#define GPMC_NAND_COMMAND 0x00000005
> > > +#define GPMC_NAND_ADDRESS 0x00000006
> > > +#define GPMC_NAND_DATA 0x00000007
> > > +#define GPMC_STATUS_BUFFER 0x00000008 /* 1: buffer is available
> to write */
> > > +#define GPMC_PREFETCH_FIFO_CNT 0x00000009 /* bytes available in FIFO
> for r/w */
> > > +#define GPMC_PREFETCH_COUNT 0x0000000A /* remaining bytes to be
> read/write*/
> > > +#define GPMC_GET_SET_IRQ_STATUS 0x0000000B
> > > +
> > > +/* ECC commands */
> > > +#define GPMC_ECC_READ 0 /* Reset Hardware ECC for read */
> > > +#define GPMC_ECC_WRITE 1 /* Reset Hardware ECC for write */
> > > +#define GPMC_ECC_READSYN 2 /* Reset before syndrom is read back
> */
> > >
> > > #define GPMC_CONFIG1_WRAPBURST_SUPP (1 << 31)
> > > #define GPMC_CONFIG1_READMULTIPLE_SUPP (1 << 30)
> > > @@ -56,6 +72,14 @@
> > > #define GPMC_CONFIG1_FCLK_DIV4 (GPMC_CONFIG1_FCLK_DIV(3))
> > > #define GPMC_CONFIG7_CSVALID (1 << 6)
> > >
> > > +#define GPMC_DEVICETYPE_NOR 0
> > > +#define GPMC_DEVICETYPE_NAND 2
> > > +#define GPMC_CONFIG_WRITEPROTECT 0x00000010
> > > +#define GPMC_STATUS_BUFF_EMPTY 0x00000001
> > > +#define WR_RD_PIN_MONITORING 0x00600000
> > > +#define GPMC_PREFETCH_STATUS_FIFO_CNT(val) ((val & 0x7f000000) >>
> 24)
> > > +#define GPMC_PREFETCH_STATUS_COUNT(val) (val & 0x00003fff)
> > > +
> > > /*
> > > * Note that all values in this struct are in nanoseconds, while
> > > * the register values are in gpmc_fck cycles.
> > > @@ -108,10 +132,15 @@ extern int gpmc_cs_set_reserved(int cs, int
> reserved);
> > > extern int gpmc_cs_reserved(int cs);
> > > extern int gpmc_prefetch_enable(int cs, int dma_mode,
> > > unsigned int u32_count, int
> is_write);
> > > -extern void gpmc_prefetch_reset(void);
> > > +extern int gpmc_prefetch_reset(int cs);
> > > extern int gpmc_prefetch_status(void);
> > > extern void omap3_gpmc_save_context(void);
> > > extern void omap3_gpmc_restore_context(void);
> > > extern void gpmc_init(void);
> > > +extern int gpmc_hwcontrol(int cs, int cmd, int write, int wval, int
> *rval);
> > >
> > > +int gpmc_ecc_init(int cs, int ecc_size);
> > > +int gpmc_enable_hwecc(int cs, int mode, int dev_width);
> > > +int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code);
> > > +int gpmc_ecc_reset(int cs);
> > > #endif
> > > diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
> > > index 7545568..206406b
> > > --- a/drivers/mtd/nand/omap2.c
> > > +++ b/drivers/mtd/nand/omap2.c
> > > @@ -316,7 +316,7 @@ static void omap_read_buf_pref(struct mtd_info
> *mtd, u_char *buf, int len)
> > > } while (len);
> > >
> > > /* disable and stop the PFPW engine */
> > > - gpmc_prefetch_reset();
> > > + gpmc_prefetch_reset(info->gpmc_cs);
> > Not required. see above comments.
[Ghorai] agree and will take as 4th patch as cleanup and its not matching with patch description
> >
> > > }
> > > }
> > >
> > > @@ -360,7 +360,7 @@ static void omap_write_buf_pref(struct mtd_info
> *mtd,
> > > }
> > >
> > > /* disable and stop the PFPW engine */
> > > - gpmc_prefetch_reset();
> > > + gpmc_prefetch_reset(info->gpmc_cs);
> > Not required. see above comments.
[Ghorai] agree and will take as 4th patch as cleanup and its not matching with patch description
> > > }
> > > }
> > >
> > > --
> > > To unsubscribe from this list: send the line "unsubscribe linux-omap"
> in
> > > the body of a message to majordomo@vger.kernel.org
> > > More majordomo info at http://vger.kernel.org/majordomo-info.html
> > >
> >
> >
> >
>
^ permalink raw reply [flat|nested] 102+ messages in thread
* Re: [PATCH v3 2/3] omap3 nand: cleanup virtual address usages
2010-05-19 17:24 ` Ghorai, Sukumar
@ 2010-05-19 18:07 ` Vimal Singh
2010-05-19 18:19 ` Tony Lindgren
0 siblings, 1 reply; 102+ messages in thread
From: Vimal Singh @ 2010-05-19 18:07 UTC (permalink / raw)
To: Ghorai, Sukumar
Cc: linux-omap@vger.kernel.org, linux-mtd@lists.infradead.org,
tony@atomide.com, sakoman@gmail.com, mike@compulab.co.il,
Artem.Bityutskiy@nokia.com
On Wed, May 19, 2010 at 10:54 PM, Ghorai, Sukumar <s-ghorai@ti.com> wrote:
>> > /* take care of subpage reads */
>> > for (; len % 4 != 0; ) {
>> > *buf++ = __raw_readb(info->nand.IO_ADDR_R);
>> > len--;
>> > }
>> > - p = (u32 *) buf;
>>
>> Above code had an issue, which was fixed by this commit:
>> http://git.infradead.org/mtd-
>> 2.6.git/commitdiff/c3341d0ceb4de1680572024f50233403c6a8b10d
>>
>> I would suggest you to prepare your patch on MTD tree.
> [Ghorai] Patches started posting on lo. And lets continue the same.
Not sure about this. Its your/Tony's call.
>>
>> >
>> > /* configure and start prefetch transfer */
>> > ret = gpmc_prefetch_enable(info->gpmc_cs, 0x0, len, 0x0);
>> > @@ -307,17 +265,18 @@ static void omap_read_buf_pref(struct mtd_info
>> *mtd, u_char *buf, int len)
>> > else
>> > omap_read_buf8(mtd, buf, len);
>> > } else {
>> > + p = (u32 *) buf;
>> > do {
>> > - pfpw_status = gpmc_prefetch_status();
>> > - r_count = ((pfpw_status >> 24) & 0x7F) >> 2;
>> > - ioread32_rep(info->nand_pref_fifo_add, p,
>> r_count);
>> > + gpmc_hwcontrol(info->gpmc_cs,
>> > + GPMC_PREFETCH_FIFO_CNT, 0, 0, &r_count);
>> > + r_count = r_count >> 2;
>> > + ioread32_rep(info->nand.IO_ADDR_R, p, r_count);
>> > p += r_count;
>> > - len -= r_count << 2;
>> > + len -= (r_count << 2);
>>
>> Braces are not required here.
> [Ghorai] thanks
>>
>> > } while (len);
>> > -
>>
>> After call to 'gpmc_prefetch_enable', next line are:
>> if (ret) {
>> /* PFPW engine is busy, use cpu copy method */
>> if (info->nand.options & NAND_BUSWIDTH_16)
>> ...
>> ...
>> > - /* disable and stop the PFPW engine */
>> > - gpmc_prefetch_reset(info->gpmc_cs);
>> > }
>>
>> So, if above 'if' fails, driver will not get prefetch engine (it was
>> already busy). Then it doesn't makes sense to call for __reset__.
> [Ghorai] I will take this clean up as 4th patch. As its not matching with patch description.
>>
>> > + /* disable and stop the PFPW engine */
>> > + gpmc_prefetch_reset(info->gpmc_cs);
>>
>> (Also see my comments on your other patch.)
> [Ghorai] Agree and I will take this kind of cleanup as 4th patch
>>
>> > }
>> >
>> > /**
>> > @@ -331,13 +290,13 @@ static void omap_write_buf_pref(struct mtd_info
>> *mtd,
>> > {
>> > struct omap_nand_info *info = container_of(mtd,
>> > struct omap_nand_info,
>> mtd);
>> > - uint32_t pfpw_status = 0, w_count = 0;
>> > + uint32_t pref_count = 0, w_count = 0;
>> > int i = 0, ret = 0;
>> > - u16 *p = (u16 *) buf;
>> > + u16 *p;
>> >
>> > /* take care of subpage writes */
>> > if (len % 2 != 0) {
>> > - writeb(*buf, info->nand.IO_ADDR_R);
>> > + writeb(*buf, info->nand.IO_ADDR_W);
>> > p = (u16 *)(buf + 1);
>> > len--;
>> > }
>> > @@ -351,17 +310,22 @@ static void omap_write_buf_pref(struct mtd_info
>> *mtd,
>> > else
>> > omap_write_buf8(mtd, buf, len);
>> > } else {
>> > - pfpw_status = gpmc_prefetch_status();
>> > - while (pfpw_status & 0x3FFF) {
>> > - w_count = ((pfpw_status >> 24) & 0x7F) >> 1;
>> > + p = (u16 *) buf;
>> > + while (len) {
>> > + gpmc_hwcontrol(info->gpmc_cs,
>> > + GPMC_PREFETCH_FIFO_CNT, 0, 0,
>> &w_count);
>> > + w_count = w_count >> 1;
>> > for (i = 0; (i < w_count) && len; i++, len -= 2)
>> > - iowrite16(*p++, info-
>> >nand_pref_fifo_add);
>> > - pfpw_status = gpmc_prefetch_status();
>> > + iowrite16(*p++, info->nand.IO_ADDR_W);
>> > }
>> > -
>> > - /* disable and stop the PFPW engine */
>> > - gpmc_prefetch_reset(info->gpmc_cs);
>> > + /* wait for data to flushed-out before reset the
>> prefetch */
>> > + do {
>> > + gpmc_hwcontrol(info->gpmc_cs,
>> > + GPMC_PREFETCH_COUNT, 0, 0, &pref_count);
>> > + } while (pref_count);
>> > }
>> > + /* disable and stop the PFPW engine */
>> > + gpmc_prefetch_reset(info->gpmc_cs);
>>
>> Same as above.
> [Ghorai] Agree and I will take this kind of cleanup as 4th patch, as its not matching with patch description.
>>
>>
>> > }
>> >
>> > #ifdef CONFIG_MTD_NAND_OMAP_PREFETCH_DMA
>> > @@ -448,8 +412,10 @@ static inline int omap_nand_dma_transfer(struct
>> mtd_info *mtd, void *addr,
>> > /* setup and start DMA using dma_addr */
>> > wait_for_completion(&info->comp);
>> >
>> > - while (0x3fff & (prefetch_status = gpmc_prefetch_status()))
>> > - ;
>> > + do {
>> > + gpmc_hwcontrol(info->gpmc_cs,
>> > + GPMC_PREFETCH_COUNT, 0, 0,
>> &prefetch_status);
>> > + } while (prefetch_status);
>> > /* disable and stop the PFPW engine */
>> > gpmc_prefetch_reset();
>> >
>> > @@ -502,7 +468,7 @@ static void omap_write_buf_dma_pref(struct mtd_info
>> *mtd,
>> > omap_write_buf_pref(mtd, buf, len);
>> > else
>> > /* start transfer in DMA mode */
>> > - omap_nand_dma_transfer(mtd, buf, len, 0x1);
>> > + omap_nand_dma_transfer(mtd, (u_char *) buf, len, 0x1);
>>
>> This is already fixed. See commit:
>> http://git.infradead.org/mtd-
>> 2.6.git/commitdiff/bdaefc41627b6f2815ef7aa476dfa4ebb3ad499f
> [Ghorai] thanks I will omit this from this patch
>>
>>
>> Rest, patches looks good. It is a good clean-up all together.
> [Ghorai] Is it possible for you to check once again if you have any additional comments! This is to identify the issue if any at early stage.
Yeah, I can understand. I tried to review it fully, but can not say if
still something left and gets attention later on. Even sometimes they
will become visible when you fix current one.
As of now this is all what I had.
--
Regards,
Vimal Singh
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 102+ messages in thread
* Re: [PATCH v3 2/3] omap3 nand: cleanup virtual address usages
2010-05-19 18:07 ` Vimal Singh
@ 2010-05-19 18:19 ` Tony Lindgren
0 siblings, 0 replies; 102+ messages in thread
From: Tony Lindgren @ 2010-05-19 18:19 UTC (permalink / raw)
To: Vimal Singh
Cc: Ghorai, Sukumar, linux-omap@vger.kernel.org,
linux-mtd@lists.infradead.org, sakoman@gmail.com,
mike@compulab.co.il, Artem.Bityutskiy@nokia.com
* Vimal Singh <vimal.newwork@gmail.com> [100519 11:02]:
> On Wed, May 19, 2010 at 10:54 PM, Ghorai, Sukumar <s-ghorai@ti.com> wrote:
> >> > /* take care of subpage reads */
> >> > for (; len % 4 != 0; ) {
> >> > *buf++ = __raw_readb(info->nand.IO_ADDR_R);
> >> > len--;
> >> > }
> >> > - p = (u32 *) buf;
> >>
> >> Above code had an issue, which was fixed by this commit:
> >> http://git.infradead.org/mtd-
> >> 2.6.git/commitdiff/c3341d0ceb4de1680572024f50233403c6a8b10d
> >>
> >> I would suggest you to prepare your patch on MTD tree.
> > [Ghorai] Patches started posting on lo. And lets continue the same.
>
> Not sure about this. Its your/Tony's call.
I'd assume that fix is on it's way to the mainline kernel,
looks like a trivial rebase after the merge window is over.
Anyways, this will not make it this merge window, we're
out of time.
Regards,
Tony
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 102+ messages in thread
* Re: [PATCH v3 1/3] omap3 gpmc: functionality enhancement
2010-05-19 18:04 ` Ghorai, Sukumar
@ 2010-05-19 18:30 ` Vimal Singh
2010-05-20 5:38 ` Ghorai, Sukumar
2010-05-25 14:37 ` Ghorai, Sukumar
0 siblings, 2 replies; 102+ messages in thread
From: Vimal Singh @ 2010-05-19 18:30 UTC (permalink / raw)
To: Ghorai, Sukumar
Cc: linux-omap@vger.kernel.org, linux-mtd@lists.infradead.org,
tony@atomide.com, sakoman@gmail.com, mike@compulab.co.il,
Artem.Bityutskiy@nokia.com, peter.barada@gmail.com
On Wed, May 19, 2010 at 11:34 PM, Ghorai, Sukumar <s-ghorai@ti.com> wrote:
>> > > +
>> > > + case GPMC_CONFIG_RDY_BSY:
>> > > + regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
>> > > + regval |= WR_RD_PIN_MONITORING;
>> > > + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
>> > > + break;
>> >
>> > IIRC, at least in OMAP2/3, ready/busy pin is not in use (not connected).
>>
>> On the Logic OMAP3530 LV SOM and Torpedo modules, the R/B# pin of the
>> NAND in the Micron mt29c2g4maklajg-6it POP part is connected to the
>> WAIT0 pin on the OMAP3530 and I'm looking to use it to speed up NAND
>> accesses
> [Ghorai] So better keep this feature,
Yes, looks like there are some boards which can still take advantage of this.
>>
[...]
>> > > @@ -456,13 +572,20 @@ EXPORT_SYMBOL(gpmc_prefetch_enable);
>> > > /**
>> > > * gpmc_prefetch_reset - disables and stops the prefetch engine
>> > > */
>> > > -void gpmc_prefetch_reset(void)
>> > > +int gpmc_prefetch_reset(int cs)
>> > > {
>> > > + if (gpmc_pref_used == cs)
>> > > + gpmc_pref_used = -EINVAL;
>> > > + else
>> > > + return -EINVAL;
>> > > +
>> >
>> > This is also not required. As, this function will be called only if
>> > prefetch was used.
> [Ghorai] Agree. Can you see this input too?
> http://www.mail-archive.com/linux-omap@vger.kernel.org/msg28520.html
Exactly, this is what I am telling here. Enable prefetch engine call
is already being check for *busy* or not.
>
[...]
>> > > +int gpmc_ecc_init(int cs, int ecc_size)
>> > > +{
>> > > + unsigned int val = 0x0;
>> > > +
>> > > + /* check if ecc engine already by another cs */
>> > > + if (gpmc_ecc_used == -EINVAL)
>> > > + gpmc_ecc_used = cs;
>> > > + else
>> > > + return -EBUSY;
>> > Here few things need be to consider:
>> > 1. 'init' is supposed to done once for every instance of driver during
>> probe
>> > 2. But ECC engine, too, have only one instance at a time, So
>> > 3. As long as all NAND chip are supposed to use same ECC machenism, we
>> > can go for only one time 'init' for all drivers, perhaps in
>> > gpmc_nand.c.
>> > 4. But in case, different instances of driver (or NAND chip) requires
>> > different ECC machenism (for ex. Hamming or BCH, or even with
>> > different capabilities of error correction),
>> > this will no longer vailid. Then rather we should have something like
>> > 'gpmc_ecc_config' call to configer ECC engine for everytime a driver
>> > needs it (something like as it is done for prefetch engine).
> [Ghorai]
> a. do you think it will reduce the throughput?
No. But in current implementation it will be called for each instance
driver. (see my 3rd point)
> b. Moreover I think we will take this as 5th patch as cleanup/ improvemnt.
> c. And how to know that ECC engine is in used other driver should not use it? Any bit to know that ecc engine is busy, as we check for prefetch?
Do not really remember config registers. Perhaps there is no way.
But I guess you should check into register GPMC_ECC_CONFIG at bit 1.
This is the bit we are setting to enable ECC calculation, IIRC.
> d. any further input on http://www.mail-archive.com/linux-omap@vger.kernel.org/msg28520.html
And this what I was suggesting in my point 4. In my example
'gpmc_ecc_config' is analogy to 'gpmc_ecc_request'.
I said *config*, since in such scenario you need to configer HW
ECCconfig register everytime as well, rather just checking
availability and enabling.
>
[...]
>> > > +int gpmc_ecc_reset(int cs)
>> > > +{
>> > > + if (gpmc_ecc_used == cs)
>> > > + gpmc_ecc_used = -EINVAL;
>> > > + else
>> > > + return -EINVAL;
>> > > +
>> > > + return 0;
>> > > +}
I guess in this function you should also clear gpmc ecc config
register explicitly.
--
Regards,
Vimal Singh
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 102+ messages in thread
* RE: [PATCH v3 1/3] omap3 gpmc: functionality enhancement
2010-05-19 18:30 ` Vimal Singh
@ 2010-05-20 5:38 ` Ghorai, Sukumar
2010-05-20 14:34 ` Vimal Singh
2010-05-25 14:37 ` Ghorai, Sukumar
1 sibling, 1 reply; 102+ messages in thread
From: Ghorai, Sukumar @ 2010-05-20 5:38 UTC (permalink / raw)
To: Vimal Singh
Cc: linux-omap@vger.kernel.org, linux-mtd@lists.infradead.org,
tony@atomide.com, sakoman@gmail.com, mike@compulab.co.il,
Artem.Bityutskiy@nokia.com, peter.barada@gmail.com
Vimal,
> -----Original Message-----
> From: Vimal Singh [mailto:vimal.newwork@gmail.com]
> Sent: 2010-05-20 00:01
> To: Ghorai, Sukumar
> Cc: linux-omap@vger.kernel.org; linux-mtd@lists.infradead.org;
> tony@atomide.com; sakoman@gmail.com; mike@compulab.co.il;
> Artem.Bityutskiy@nokia.com; peter.barada@gmail.com
> Subject: Re: [PATCH v3 1/3] omap3 gpmc: functionality enhancement
>
> On Wed, May 19, 2010 at 11:34 PM, Ghorai, Sukumar <s-ghorai@ti.com> wrote:
> >> > > +
> >> > > + case GPMC_CONFIG_RDY_BSY:
> >> > > + regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
> >> > > + regval |= WR_RD_PIN_MONITORING;
> >> > > + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
> >> > > + break;
> >> >
> >> > IIRC, at least in OMAP2/3, ready/busy pin is not in use (not
> connected).
> >>
> >> On the Logic OMAP3530 LV SOM and Torpedo modules, the R/B# pin of the
> >> NAND in the Micron mt29c2g4maklajg-6it POP part is connected to the
> >> WAIT0 pin on the OMAP3530 and I'm looking to use it to speed up NAND
> >> accesses
> > [Ghorai] So better keep this feature,
>
> Yes, looks like there are some boards which can still take advantage of
> this.
>
> >>
> [...]
> >> > > @@ -456,13 +572,20 @@ EXPORT_SYMBOL(gpmc_prefetch_enable);
> >> > > /**
> >> > > * gpmc_prefetch_reset - disables and stops the prefetch engine
> >> > > */
> >> > > -void gpmc_prefetch_reset(void)
> >> > > +int gpmc_prefetch_reset(int cs)
> >> > > {
> >> > > + if (gpmc_pref_used == cs)
> >> > > + gpmc_pref_used = -EINVAL;
> >> > > + else
> >> > > + return -EINVAL;
> >> > > +
> >> >
> >> > This is also not required. As, this function will be called only if
> >> > prefetch was used.
> > [Ghorai] Agree. Can you see this input too?
> > http://www.mail-archive.com/linux-omap@vger.kernel.org/msg28520.html
>
> Exactly, this is what I am telling here. Enable prefetch engine call
> is already being check for *busy* or not.
>
> >
> [...]
> >> > > +int gpmc_ecc_init(int cs, int ecc_size)
> >> > > +{
> >> > > + unsigned int val = 0x0;
> >> > > +
> >> > > + /* check if ecc engine already by another cs */
> >> > > + if (gpmc_ecc_used == -EINVAL)
> >> > > + gpmc_ecc_used = cs;
> >> > > + else
> >> > > + return -EBUSY;
> >> > Here few things need be to consider:
> >> > 1. 'init' is supposed to done once for every instance of driver
> during
> >> probe
> >> > 2. But ECC engine, too, have only one instance at a time, So
> >> > 3. As long as all NAND chip are supposed to use same ECC machenism,
> we
> >> > can go for only one time 'init' for all drivers, perhaps in
> >> > gpmc_nand.c.
> >> > 4. But in case, different instances of driver (or NAND chip) requires
> >> > different ECC machenism (for ex. Hamming or BCH, or even with
> >> > different capabilities of error correction),
> >> > this will no longer vailid. Then rather we should have something like
> >> > 'gpmc_ecc_config' call to configer ECC engine for everytime a driver
> >> > needs it (something like as it is done for prefetch engine).
> > [Ghorai]
> > a. do you think it will reduce the throughput?
> No. But in current implementation it will be called for each instance
> driver. (see my 3rd point)
>
> > b. Moreover I think we will take this as 5th patch as cleanup/
> improvemnt.
> > c. And how to know that ECC engine is in used other driver should not
> use it? Any bit to know that ecc engine is busy, as we check for prefetch?
> Do not really remember config registers. Perhaps there is no way.
> But I guess you should check into register GPMC_ECC_CONFIG at bit 1.
> This is the bit we are setting to enable ECC calculation, IIRC.
>
> > d. any further input on http://www.mail-archive.com/linux-
> omap@vger.kernel.org/msg28520.html
> And this what I was suggesting in my point 4. In my example
> 'gpmc_ecc_config' is analogy to 'gpmc_ecc_request'.
> I said *config*, since in such scenario you need to configer HW
> ECCconfig register everytime as well, rather just checking
> availability and enabling.
[Ghorai] still I feel we should not mix this patch with cleanup. And yes if possible this will be the 5th one as cleanup.
4th one - prefetch cleanup
5th one - ecc cleanup.
Do you think still missing anything for this patch?
>
> >
> [...]
> >> > > +int gpmc_ecc_reset(int cs)
> >> > > +{
> >> > > + if (gpmc_ecc_used == cs)
> >> > > + gpmc_ecc_used = -EINVAL;
> >> > > + else
> >> > > + return -EINVAL;
> >> > > +
> >> > > + return 0;
> >> > > +}
>
> I guess in this function you should also clear gpmc ecc config
> register explicitly.
>
>
> --
> Regards,
> Vimal Singh
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 102+ messages in thread
* Re: [PATCH v3 1/3] omap3 gpmc: functionality enhancement
2010-05-20 5:38 ` Ghorai, Sukumar
@ 2010-05-20 14:34 ` Vimal Singh
0 siblings, 0 replies; 102+ messages in thread
From: Vimal Singh @ 2010-05-20 14:34 UTC (permalink / raw)
To: Ghorai, Sukumar
Cc: linux-omap@vger.kernel.org, linux-mtd@lists.infradead.org,
tony@atomide.com, sakoman@gmail.com, mike@compulab.co.il,
Artem.Bityutskiy@nokia.com, peter.barada@gmail.com
On Thu, May 20, 2010 at 11:08 AM, Ghorai, Sukumar <s-ghorai@ti.com> wrote:
> Vimal,
>
>> -----Original Message-----
>> From: Vimal Singh [mailto:vimal.newwork@gmail.com]
>> Sent: 2010-05-20 00:01
>> To: Ghorai, Sukumar
>> Cc: linux-omap@vger.kernel.org; linux-mtd@lists.infradead.org;
>> tony@atomide.com; sakoman@gmail.com; mike@compulab.co.il;
>> Artem.Bityutskiy@nokia.com; peter.barada@gmail.com
>> Subject: Re: [PATCH v3 1/3] omap3 gpmc: functionality enhancement
>>
>> On Wed, May 19, 2010 at 11:34 PM, Ghorai, Sukumar <s-ghorai@ti.com> wrote:
>> >> > > +
>> >> > > + case GPMC_CONFIG_RDY_BSY:
>> >> > > + regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
>> >> > > + regval |= WR_RD_PIN_MONITORING;
>> >> > > + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
>> >> > > + break;
>> >> >
>> >> > IIRC, at least in OMAP2/3, ready/busy pin is not in use (not
>> connected).
>> >>
>> >> On the Logic OMAP3530 LV SOM and Torpedo modules, the R/B# pin of the
>> >> NAND in the Micron mt29c2g4maklajg-6it POP part is connected to the
>> >> WAIT0 pin on the OMAP3530 and I'm looking to use it to speed up NAND
>> >> accesses
>> > [Ghorai] So better keep this feature,
>>
>> Yes, looks like there are some boards which can still take advantage of
>> this.
>>
>> >>
>> [...]
>> >> > > @@ -456,13 +572,20 @@ EXPORT_SYMBOL(gpmc_prefetch_enable);
>> >> > > /**
>> >> > > * gpmc_prefetch_reset - disables and stops the prefetch engine
>> >> > > */
>> >> > > -void gpmc_prefetch_reset(void)
>> >> > > +int gpmc_prefetch_reset(int cs)
>> >> > > {
>> >> > > + if (gpmc_pref_used == cs)
>> >> > > + gpmc_pref_used = -EINVAL;
>> >> > > + else
>> >> > > + return -EINVAL;
>> >> > > +
>> >> >
>> >> > This is also not required. As, this function will be called only if
>> >> > prefetch was used.
>> > [Ghorai] Agree. Can you see this input too?
>> > http://www.mail-archive.com/linux-omap@vger.kernel.org/msg28520.html
>>
>> Exactly, this is what I am telling here. Enable prefetch engine call
>> is already being check for *busy* or not.
>>
>> >
>> [...]
>> >> > > +int gpmc_ecc_init(int cs, int ecc_size)
>> >> > > +{
>> >> > > + unsigned int val = 0x0;
>> >> > > +
>> >> > > + /* check if ecc engine already by another cs */
>> >> > > + if (gpmc_ecc_used == -EINVAL)
>> >> > > + gpmc_ecc_used = cs;
>> >> > > + else
>> >> > > + return -EBUSY;
>> >> > Here few things need be to consider:
>> >> > 1. 'init' is supposed to done once for every instance of driver
>> during
>> >> probe
>> >> > 2. But ECC engine, too, have only one instance at a time, So
>> >> > 3. As long as all NAND chip are supposed to use same ECC machenism,
>> we
>> >> > can go for only one time 'init' for all drivers, perhaps in
>> >> > gpmc_nand.c.
>> >> > 4. But in case, different instances of driver (or NAND chip) requires
>> >> > different ECC machenism (for ex. Hamming or BCH, or even with
>> >> > different capabilities of error correction),
>> >> > this will no longer vailid. Then rather we should have something like
>> >> > 'gpmc_ecc_config' call to configer ECC engine for everytime a driver
>> >> > needs it (something like as it is done for prefetch engine).
>> > [Ghorai]
>> > a. do you think it will reduce the throughput?
>> No. But in current implementation it will be called for each instance
>> driver. (see my 3rd point)
>>
>> > b. Moreover I think we will take this as 5th patch as cleanup/
>> improvemnt.
>> > c. And how to know that ECC engine is in used other driver should not
>> use it? Any bit to know that ecc engine is busy, as we check for prefetch?
>> Do not really remember config registers. Perhaps there is no way.
>> But I guess you should check into register GPMC_ECC_CONFIG at bit 1.
>> This is the bit we are setting to enable ECC calculation, IIRC.
>>
>> > d. any further input on http://www.mail-archive.com/linux-
>> omap@vger.kernel.org/msg28520.html
>> And this what I was suggesting in my point 4. In my example
>> 'gpmc_ecc_config' is analogy to 'gpmc_ecc_request'.
>> I said *config*, since in such scenario you need to configer HW
>> ECCconfig register everytime as well, rather just checking
>> availability and enabling.
> [Ghorai] still I feel we should not mix this patch with cleanup. And yes if possible this will be the 5th one as cleanup.
> 4th one - prefetch cleanup
> 5th one - ecc cleanup.
> Do you think still missing anything for this patch?
As long as you take care of current comments, I do not have any
further comment for now.
--
Regards,
Vimal Singh
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 102+ messages in thread
* RE: [PATCH v3 1/3] omap3 gpmc: functionality enhancement
2010-05-19 18:30 ` Vimal Singh
2010-05-20 5:38 ` Ghorai, Sukumar
@ 2010-05-25 14:37 ` Ghorai, Sukumar
2010-05-25 15:34 ` Vimal Singh
1 sibling, 1 reply; 102+ messages in thread
From: Ghorai, Sukumar @ 2010-05-25 14:37 UTC (permalink / raw)
To: Vimal Singh
Cc: linux-omap@vger.kernel.org, linux-mtd@lists.infradead.org,
tony@atomide.com, sakoman@gmail.com, mike@compulab.co.il,
Artem.Bityutskiy@nokia.com, peter.barada@gmail.com
Vimal,
> -----Original Message-----
> From: Vimal Singh [mailto:vimal.newwork@gmail.com]
> Sent: Thursday, May 20, 2010 12:01 AM
> To: Ghorai, Sukumar
> Cc: linux-omap@vger.kernel.org; linux-mtd@lists.infradead.org;
> tony@atomide.com; sakoman@gmail.com; mike@compulab.co.il;
> Artem.Bityutskiy@nokia.com; peter.barada@gmail.com
> Subject: Re: [PATCH v3 1/3] omap3 gpmc: functionality enhancement
>
> On Wed, May 19, 2010 at 11:34 PM, Ghorai, Sukumar <s-ghorai@ti.com> wrote:
> >> > > +
> >> > > + case GPMC_CONFIG_RDY_BSY:
> >> > > + regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
> >> > > + regval |= WR_RD_PIN_MONITORING;
> >> > > + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
> >> > > + break;
> >> >
> >> > IIRC, at least in OMAP2/3, ready/busy pin is not in use (not
> connected).
> >>
> >> On the Logic OMAP3530 LV SOM and Torpedo modules, the R/B# pin of the
> >> NAND in the Micron mt29c2g4maklajg-6it POP part is connected to the
> >> WAIT0 pin on the OMAP3530 and I'm looking to use it to speed up NAND
> >> accesses
> > [Ghorai] So better keep this feature,
>
> Yes, looks like there are some boards which can still take advantage of
> this.
>
> >>
> [...]
> >> > > @@ -456,13 +572,20 @@ EXPORT_SYMBOL(gpmc_prefetch_enable);
> >> > > /**
> >> > > * gpmc_prefetch_reset - disables and stops the prefetch engine
> >> > > */
> >> > > -void gpmc_prefetch_reset(void)
> >> > > +int gpmc_prefetch_reset(int cs)
> >> > > {
> >> > > + if (gpmc_pref_used == cs)
> >> > > + gpmc_pref_used = -EINVAL;
> >> > > + else
> >> > > + return -EINVAL;
> >> > > +
> >> >
> >> > This is also not required. As, this function will be called only if
> >> > prefetch was used.
> > [Ghorai] Agree. Can you see this input too?
> > http://www.mail-archive.com/linux-omap@vger.kernel.org/msg28520.html
>
> Exactly, this is what I am telling here. Enable prefetch engine call
> is already being check for *busy* or not.
[Ghorai] Agree.
>
> >
> [...]
> >> > > +int gpmc_ecc_init(int cs, int ecc_size)
> >> > > +{
> >> > > + unsigned int val = 0x0;
> >> > > +
> >> > > + /* check if ecc engine already by another cs */
> >> > > + if (gpmc_ecc_used == -EINVAL)
> >> > > + gpmc_ecc_used = cs;
> >> > > + else
> >> > > + return -EBUSY;
> >> > Here few things need be to consider:
> >> > 1. 'init' is supposed to done once for every instance of driver
> during
> >> probe
> >> > 2. But ECC engine, too, have only one instance at a time, So
> >> > 3. As long as all NAND chip are supposed to use same ECC machenism,
> we
> >> > can go for only one time 'init' for all drivers, perhaps in
> >> > gpmc_nand.c.
> >> > 4. But in case, different instances of driver (or NAND chip) requires
> >> > different ECC machenism (for ex. Hamming or BCH, or even with
> >> > different capabilities of error correction),
> >> > this will no longer vailid. Then rather we should have something like
> >> > 'gpmc_ecc_config' call to configer ECC engine for everytime a driver
> >> > needs it (something like as it is done for prefetch engine).
> > [Ghorai]
> > a. do you think it will reduce the throughput?
> No. But in current implementation it will be called for each instance
> driver. (see my 3rd point)
>
> > b. Moreover I think we will take this as 5th patch as cleanup/
> improvemnt.
> > c. And how to know that ECC engine is in used other driver should not
> use it? Any bit to know that ecc engine is busy, as we check for prefetch?
> Do not really remember config registers. Perhaps there is no way.
> But I guess you should check into register GPMC_ECC_CONFIG at bit 1.
> This is the bit we are setting to enable ECC calculation, IIRC.
[Ghorai] there are two functions -
info->nand.ecc.calculate = omap_calculate_ecc;
info->nand.ecc.hwctl = omap_enable_hwecc;
And GPMC_ECC_CONFIG register..
3:1 ECCCS Selects the CS where ECC is computed
0 ECCENABLE Enables the ECC feature
Now we enable omap_enable_hwecc (with GPMC_ECC_CONFIG[ECCENABLE]=1); and its get disabled (automatically) when ecc_size data transfer over. But say still it did not read the ecc value yet (omap_calculate_ecc).
So how to protect following omap_enable_hwecc() before omap_calculate_ecc() without additional flag? Any input is welcome.
>
> > d. any further input on http://www.mail-archive.com/linux-
> omap@vger.kernel.org/msg28520.html
> And this what I was suggesting in my point 4. In my example
> 'gpmc_ecc_config' is analogy to 'gpmc_ecc_request'.
> I said *config*, since in such scenario you need to configer HW
> ECCconfig register everytime as well, rather just checking
> availability and enabling.
[Ghorai] As above.
>
> >
> [...]
> >> > > +int gpmc_ecc_reset(int cs)
> >> > > +{
> >> > > + if (gpmc_ecc_used == cs)
> >> > > + gpmc_ecc_used = -EINVAL;
> >> > > + else
> >> > > + return -EINVAL;
> >> > > +
> >> > > + return 0;
> >> > > +}
>
> I guess in this function you should also clear gpmc ecc config
> register explicitly.
>
>
> --
> Regards,
> Vimal Singh
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 102+ messages in thread
* Re: [PATCH v3 1/3] omap3 gpmc: functionality enhancement
2010-05-25 14:37 ` Ghorai, Sukumar
@ 2010-05-25 15:34 ` Vimal Singh
0 siblings, 0 replies; 102+ messages in thread
From: Vimal Singh @ 2010-05-25 15:34 UTC (permalink / raw)
To: Ghorai, Sukumar
Cc: linux-omap@vger.kernel.org, linux-mtd@lists.infradead.org,
tony@atomide.com, sakoman@gmail.com, mike@compulab.co.il,
Artem.Bityutskiy@nokia.com, peter.barada@gmail.com
On Tue, May 25, 2010 at 8:07 PM, Ghorai, Sukumar <s-ghorai@ti.com> wrote:
[...]
>> > c. And how to know that ECC engine is in used other driver should not
>> use it? Any bit to know that ecc engine is busy, as we check for prefetch?
>> Do not really remember config registers. Perhaps there is no way.
>> But I guess you should check into register GPMC_ECC_CONFIG at bit 1.
>> This is the bit we are setting to enable ECC calculation, IIRC.
> [Ghorai] there are two functions -
> info->nand.ecc.calculate = omap_calculate_ecc;
> info->nand.ecc.hwctl = omap_enable_hwecc;
> And GPMC_ECC_CONFIG register..
> 3:1 ECCCS Selects the CS where ECC is computed
> 0 ECCENABLE Enables the ECC feature
> Now we enable omap_enable_hwecc (with GPMC_ECC_CONFIG[ECCENABLE]=1); and its get disabled (automatically) when ecc_size data transfer over.
> But say still it did not read the ecc value yet (omap_calculate_ecc).
> So how to protect following omap_enable_hwecc() before omap_calculate_ecc() without additional flag? Any input is welcome.
Oh yes, that's is a problem. Perhaps in that case you have to protect
it in very much same way you already did.
--
Regards,
Vimal Singh
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 102+ messages in thread
* [PATCH v4 0/3] omap3 nand: cleanup exiting platform related code
[not found] <Sukumar Ghorai <s-ghorai@ti.com>
` (12 preceding siblings ...)
2010-05-18 11:16 ` [PATCH v3 0/3] omap3 nand: cleanup exiting platform related code Sukumar Ghorai
@ 2010-05-27 13:24 ` Sukumar Ghorai
2010-05-27 13:24 ` [PATCH v4 1/3] omap3 gpmc: functionality enhancement Sukumar Ghorai
2010-06-04 7:40 ` [PATCH v5 0/3] omap3 nand: cleanup exiting platform related code Sukumar Ghorai
2010-06-16 11:39 ` [PATCH v3 0/8] nand support on omap3 boards Sukumar Ghorai
15 siblings, 1 reply; 102+ messages in thread
From: Sukumar Ghorai @ 2010-05-27 13:24 UTC (permalink / raw)
To: linux-omap; +Cc: Sukumar Ghorai
The following set of patches applies on top of for-next branch.
http://git.kernel.org/?p=linux/kernel/git/tmlind/linux-omap-2.6.git
Patches verified on: omap3430-SDP, omap3630-sdp, zoom3 and beagle board
And these are the patches required to address the following input -
1. The NAND driver needs to stop tinkering with the GPMC registers
The omap General Purpose Memory Controller (GPMC) registers are omap
specific, and not driver specific. Tinkering with these registers can
cause issues with the other devices on the GPMC.
2. Passing hardcoded GPMC_CS0_BASE needs to go from the board files
Passing hardcoded GPMC virtual addressess is sure way to mess up things.
This should all become unnecessary once the NAND drivers stops messing
with the GPMC registers directly.
Discussion: http://www.mail-archive.com/linux-omap@vger.kernel.org/msg27630.html
v3: http://www.mail-archive.com/linux-omap@vger.kernel.org/msg28715.html
Functions related to ecc and prefetch engine are optimized.
v2: http://www.mail-archive.com/linux-omap@vger.kernel.org/msg28467.html
Few functionality was missing like - There should be some locking
as only one chipselect can use the ECC or prefetch engine at a time.
If you have NAND in two chipselects, bad things would happen.
v1: http://www.mail-archive.com/linux-omap@vger.kernel.org/msg28164.html
Additionally, it was needed to implement more functions for the
platform init code to use.
Sukumar Ghorai (3):
omap3 gpmc: functionality enhancement
omap3 nand: cleanup virtual address usages
omap3 nand: fix issue in board file to detect nand
arch/arm/mach-omap2/board-cm-t35.c | 20 +---
arch/arm/mach-omap2/board-devkit8000.c | 25 +---
arch/arm/mach-omap2/board-omap3beagle.c | 24 +---
arch/arm/mach-omap2/board-omap3touchbook.c | 25 +---
arch/arm/mach-omap2/board-overo.c | 24 +---
arch/arm/mach-omap2/gpmc-nand.c | 39 ++----
arch/arm/mach-omap2/gpmc.c | 219 +++++++++++++++++++++++++--
arch/arm/plat-omap/include/plat/gpmc.h | 36 ++++-
arch/arm/plat-omap/include/plat/nand.h | 6 +-
drivers/mtd/nand/omap2.c | 229 ++++++++--------------------
10 files changed, 320 insertions(+), 327 deletions(-)
^ permalink raw reply [flat|nested] 102+ messages in thread
* [PATCH v4 1/3] omap3 gpmc: functionality enhancement
2010-05-27 13:24 ` [PATCH v4 0/3] omap3 nand: cleanup exiting platform related code Sukumar Ghorai
@ 2010-05-27 13:24 ` Sukumar Ghorai
2010-05-27 13:24 ` [PATCH v4 2/3] omap3 nand: cleanup virtual address usages Sukumar Ghorai
2010-05-27 18:26 ` [PATCH v4 1/3] omap3 gpmc: functionality enhancement Vimal Singh
0 siblings, 2 replies; 102+ messages in thread
From: Sukumar Ghorai @ 2010-05-27 13:24 UTC (permalink / raw)
To: linux-omap; +Cc: Sukumar Ghorai
few functions added in gpmc module and to be used by other drivers like NAND.
E.g.: - ioctl function
- ecc functions
Signed-off-by: Sukumar Ghorai <s-ghorai@ti.com>
---
arch/arm/mach-omap2/gpmc.c | 219 ++++++++++++++++++++++++++++++--
arch/arm/plat-omap/include/plat/gpmc.h | 33 +++++-
drivers/mtd/nand/omap2.c | 4 +-
3 files changed, 239 insertions(+), 17 deletions(-)
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index 5bc3ca0..48b5af0
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -46,8 +46,9 @@
#define GPMC_ECC_CONFIG 0x1f4
#define GPMC_ECC_CONTROL 0x1f8
#define GPMC_ECC_SIZE_CONFIG 0x1fc
+#define GPMC_ECC1_RESULT 0x200
-#define GPMC_CS0 0x60
+#define GPMC_CS0_BASE 0x60
#define GPMC_CS_SIZE 0x30
#define GPMC_MEM_START 0x00000000
@@ -92,7 +93,8 @@ struct omap3_gpmc_regs {
static struct resource gpmc_mem_root;
static struct resource gpmc_cs_mem[GPMC_CS_NUM];
static DEFINE_SPINLOCK(gpmc_mem_lock);
-static unsigned gpmc_cs_map;
+static unsigned int gpmc_cs_map; /* flag for cs which are initialized */
+static int gpmc_ecc_used = -EINVAL; /* cs using ecc engine */
static void __iomem *gpmc_base;
@@ -108,11 +110,27 @@ static u32 gpmc_read_reg(int idx)
return __raw_readl(gpmc_base + idx);
}
+static void gpmc_cs_write_byte(int cs, int idx, u8 val)
+{
+ void __iomem *reg_addr;
+
+ reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx;
+ __raw_writeb(val, reg_addr);
+}
+
+static u8 gpmc_cs_read_byte(int cs, int idx)
+{
+ void __iomem *reg_addr;
+
+ reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx;
+ return __raw_readb(reg_addr);
+}
+
void gpmc_cs_write_reg(int cs, int idx, u32 val)
{
void __iomem *reg_addr;
- reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx;
+ reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx;
__raw_writel(val, reg_addr);
}
@@ -120,7 +138,7 @@ u32 gpmc_cs_read_reg(int cs, int idx)
{
void __iomem *reg_addr;
- reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx;
+ reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx;
return __raw_readl(reg_addr);
}
@@ -419,8 +437,100 @@ void gpmc_cs_free(int cs)
EXPORT_SYMBOL(gpmc_cs_free);
/**
+ * gpmc_hwcontrol - hardware specific access (read/ write) control
+ * @cs: chip select number
+ * @cmd: command type
+ * @write: 1 for write; 0 for read
+ * @wval: value to write
+ * @rval: read pointer
+ */
+int gpmc_hwcontrol(int cs, int cmd, int write, int wval, int *rval)
+{
+ u32 regval = 0;
+
+ if (!write && !rval)
+ return -EINVAL;
+
+ switch (cmd) {
+ case GPMC_STATUS_BUFFER:
+ regval = gpmc_read_reg(GPMC_STATUS);
+ /* 1 : buffer is available to write */
+ *rval = regval & GPMC_STATUS_BUFF_EMPTY;
+ break;
+
+ case GPMC_GET_SET_IRQ_STATUS:
+ if (write)
+ gpmc_write_reg(GPMC_IRQSTATUS, wval);
+ else
+ *rval = gpmc_read_reg(GPMC_IRQSTATUS);
+ break;
+
+ case GPMC_PREFETCH_FIFO_CNT:
+ regval = gpmc_read_reg(GPMC_PREFETCH_STATUS);
+ *rval = GPMC_PREFETCH_STATUS_FIFO_CNT(regval);
+ break;
+
+ case GPMC_PREFETCH_COUNT:
+ regval = gpmc_read_reg(GPMC_PREFETCH_STATUS);
+ *rval = GPMC_PREFETCH_STATUS_COUNT(regval);
+ break;
+
+ case GPMC_CONFIG_WP:
+ regval = gpmc_read_reg(GPMC_CONFIG);
+ if (wval)
+ regval &= ~GPMC_CONFIG_WRITEPROTECT; /* WP is ON */
+ else
+ regval |= GPMC_CONFIG_WRITEPROTECT; /* WP is OFF */
+ gpmc_write_reg(GPMC_CONFIG, regval);
+ break;
+
+ case GPMC_CONFIG_RDY_BSY:
+ regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
+ regval |= WR_RD_PIN_MONITORING;
+ gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
+ break;
+
+ case GPMC_CONFIG_DEV_SIZE:
+ regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
+ regval |= GPMC_CONFIG1_DEVICESIZE(wval);
+ gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
+ break;
+
+ case GPMC_CONFIG_DEV_TYPE:
+ regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
+ regval |= GPMC_CONFIG1_DEVICETYPE(wval);
+ if (wval == GPMC_DEVICETYPE_NOR)
+ regval |= GPMC_CONFIG1_MUXADDDATA;
+ gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
+ break;
+
+ case GPMC_NAND_COMMAND:
+ gpmc_cs_write_byte(cs, GPMC_CS_NAND_COMMAND, wval);
+ break;
+
+ case GPMC_NAND_ADDRESS:
+ gpmc_cs_write_byte(cs, GPMC_CS_NAND_ADDRESS, wval);
+ break;
+
+ case GPMC_NAND_DATA:
+ if (write)
+ gpmc_cs_write_byte(cs, GPMC_CS_NAND_DATA, wval);
+ else
+ *rval = gpmc_cs_read_byte(cs, GPMC_CS_NAND_DATA);
+ break;
+
+ default:
+ printk(KERN_ERR "gpmc_hwcontrol: Not supported\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(gpmc_hwcontrol);
+
+/**
* gpmc_prefetch_enable - configures and starts prefetch transfer
- * @cs: nand cs (chip select) number
+ * @cs: cs (chip select) number
* @dma_mode: dma mode enable (1) or disable (0)
* @u32_count: number of bytes to be transferred
* @is_write: prefetch read(0) or write post(1) mode
@@ -428,7 +538,6 @@ EXPORT_SYMBOL(gpmc_cs_free);
int gpmc_prefetch_enable(int cs, int dma_mode,
unsigned int u32_count, int is_write)
{
- uint32_t prefetch_config1;
if (!(gpmc_read_reg(GPMC_PREFETCH_CONTROL))) {
/* Set the amount of bytes to be prefetched */
@@ -437,17 +546,17 @@ int gpmc_prefetch_enable(int cs, int dma_mode,
/* Set dma/mpu mode, the prefetch read / post write and
* enable the engine. Set which cs is has requested for.
*/
- prefetch_config1 = ((cs << CS_NUM_SHIFT) |
+ gpmc_write_reg(GPMC_PREFETCH_CONFIG1, ((cs << CS_NUM_SHIFT) |
PREFETCH_FIFOTHRESHOLD |
ENABLE_PREFETCH |
(dma_mode << DMA_MPU_MODE) |
- (0x1 & is_write));
- gpmc_write_reg(GPMC_PREFETCH_CONFIG1, prefetch_config1);
+ (0x1 & is_write)));
+
+ /* Start the prefetch engine */
+ gpmc_write_reg(GPMC_PREFETCH_CONTROL, 0x1);
} else {
return -EBUSY;
}
- /* Start the prefetch engine */
- gpmc_write_reg(GPMC_PREFETCH_CONTROL, 0x1);
return 0;
}
@@ -456,13 +565,22 @@ EXPORT_SYMBOL(gpmc_prefetch_enable);
/**
* gpmc_prefetch_reset - disables and stops the prefetch engine
*/
-void gpmc_prefetch_reset(void)
+int gpmc_prefetch_reset(int cs)
{
+ u32 config1;
+
+ /* check if the same module/cs is trying to reset */
+ config1 = gpmc_read_reg(GPMC_PREFETCH_CONFIG1);
+ if (((config1 >> CS_NUM_SHIFT) & 0x7) != cs)
+ return -EINVAL;
+
/* Stop the PFPW engine */
gpmc_write_reg(GPMC_PREFETCH_CONTROL, 0x0);
/* Reset/disable the PFPW engine */
gpmc_write_reg(GPMC_PREFETCH_CONFIG1, 0x0);
+
+ return 0;
}
EXPORT_SYMBOL(gpmc_prefetch_reset);
@@ -615,3 +733,80 @@ void omap3_gpmc_restore_context(void)
}
}
#endif /* CONFIG_ARCH_OMAP3 */
+
+/**
+ * gpmc_enable_hwecc - enable hardware ecc functionality
+ * @cs: chip select number
+ * @mode: read/write mode
+ * @dev_width: device bus width(1 for x16, 0 for x8)
+ * @ecc_size: bytes for which ECC will be generated
+ */
+int gpmc_enable_hwecc(int cs, int mode, int dev_width, int ecc_size)
+{
+ unsigned int val;
+
+ /* check if ecc module is in used */
+ if (gpmc_ecc_used != -EINVAL)
+ return -EINVAL;
+
+ gpmc_ecc_used = cs;
+
+ /* clear ecc and enable bits */
+ val = ((0x00000001<<8) | 0x00000001);
+ gpmc_write_reg(GPMC_ECC_CONTROL, val);
+
+ /* program ecc and result sizes */
+ val = ((((ecc_size >> 1) - 1) << 22) | (0x0000000F));
+ gpmc_write_reg(GPMC_ECC_SIZE_CONFIG, val);
+
+ switch (mode) {
+ case GPMC_ECC_READ:
+ gpmc_write_reg(GPMC_ECC_CONTROL, 0x101);
+ break;
+ case GPMC_ECC_READSYN:
+ gpmc_write_reg(GPMC_ECC_CONTROL, 0x100);
+ break;
+ case GPMC_ECC_WRITE:
+ gpmc_write_reg(GPMC_ECC_CONTROL, 0x101);
+ break;
+ default:
+ printk(KERN_INFO "Error: Unrecognized Mode[%d]!\n", mode);
+ break;
+ }
+
+ /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */
+ val = (dev_width << 7) | (cs << 1) | (0x1);
+ gpmc_write_reg(GPMC_ECC_CONFIG, val);
+ return 0;
+}
+
+/**
+ * gpmc_calculate_ecc - generate non-inverted ecc bytes
+ * @cs: chip select number
+ * @dat: data pointer over which ecc is computed
+ * @ecc_code: ecc code buffer
+ *
+ * Using non-inverted ECC is considered ugly since writing a blank
+ * page (padding) will clear the ECC bytes. This is not a problem as long
+ * no one is trying to write data on the seemingly unused page. Reading
+ * an erased page will produce an ECC mismatch between generated and read
+ * ECC bytes that has to be dealt with separately.
+ */
+int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code)
+{
+ unsigned int val = 0x0;
+
+ if (gpmc_ecc_used != cs)
+ return -EINVAL;
+
+ /* read ecc result */
+ val = gpmc_read_reg(GPMC_ECC1_RESULT);
+ *ecc_code++ = val; /* P128e, ..., P1e */
+ *ecc_code++ = val >> 16; /* P128o, ..., P1o */
+ /* P2048o, P1024o, P512o, P256o, P2048e, P1024e, P512e, P256e */
+ *ecc_code++ = ((val >> 8) & 0x0f) | ((val >> 20) & 0xf0);
+
+ gpmc_ecc_used = -EINVAL;
+ return 0;
+}
+
diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h
index 145838a..8a1e9d9
--- a/arch/arm/plat-omap/include/plat/gpmc.h
+++ b/arch/arm/plat-omap/include/plat/gpmc.h
@@ -27,8 +27,24 @@
#define GPMC_CONFIG 0x50
#define GPMC_STATUS 0x54
-#define GPMC_CS0_BASE 0x60
-#define GPMC_CS_SIZE 0x30
+
+/* Control Commands */
+#define GPMC_CONFIG_WP 0x00000001
+#define GPMC_CONFIG_RDY_BSY 0x00000002
+#define GPMC_CONFIG_DEV_SIZE 0x00000003
+#define GPMC_CONFIG_DEV_TYPE 0x00000004
+#define GPMC_NAND_COMMAND 0x00000005
+#define GPMC_NAND_ADDRESS 0x00000006
+#define GPMC_NAND_DATA 0x00000007
+#define GPMC_STATUS_BUFFER 0x00000008 /* 1: buffer is available to write */
+#define GPMC_PREFETCH_FIFO_CNT 0x00000009 /* bytes available in FIFO for r/w */
+#define GPMC_PREFETCH_COUNT 0x0000000A /* remaining bytes to be read/write*/
+#define GPMC_GET_SET_IRQ_STATUS 0x0000000B
+
+/* ECC commands */
+#define GPMC_ECC_READ 0 /* Reset Hardware ECC for read */
+#define GPMC_ECC_WRITE 1 /* Reset Hardware ECC for write */
+#define GPMC_ECC_READSYN 2 /* Reset before syndrom is read back */
#define GPMC_CONFIG1_WRAPBURST_SUPP (1 << 31)
#define GPMC_CONFIG1_READMULTIPLE_SUPP (1 << 30)
@@ -56,6 +72,14 @@
#define GPMC_CONFIG1_FCLK_DIV4 (GPMC_CONFIG1_FCLK_DIV(3))
#define GPMC_CONFIG7_CSVALID (1 << 6)
+#define GPMC_DEVICETYPE_NOR 0
+#define GPMC_DEVICETYPE_NAND 2
+#define GPMC_CONFIG_WRITEPROTECT 0x00000010
+#define GPMC_STATUS_BUFF_EMPTY 0x00000001
+#define WR_RD_PIN_MONITORING 0x00600000
+#define GPMC_PREFETCH_STATUS_FIFO_CNT(val) ((val >> 24) & 0x7F)
+#define GPMC_PREFETCH_STATUS_COUNT(val) (val & 0x00003fff)
+
/*
* Note that all values in this struct are in nanoseconds, while
* the register values are in gpmc_fck cycles.
@@ -108,10 +132,13 @@ extern int gpmc_cs_set_reserved(int cs, int reserved);
extern int gpmc_cs_reserved(int cs);
extern int gpmc_prefetch_enable(int cs, int dma_mode,
unsigned int u32_count, int is_write);
-extern void gpmc_prefetch_reset(void);
+extern int gpmc_prefetch_reset(int cs);
extern int gpmc_prefetch_status(void);
extern void omap3_gpmc_save_context(void);
extern void omap3_gpmc_restore_context(void);
extern void gpmc_init(void);
+extern int gpmc_hwcontrol(int cs, int cmd, int write, int wval, int *rval);
+int gpmc_enable_hwecc(int cs, int mode, int dev_width, int ecc_size);
+int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code);
#endif
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index ee87325..ec8eb31
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -319,7 +319,7 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len)
} while (len);
/* disable and stop the PFPW engine */
- gpmc_prefetch_reset();
+ gpmc_prefetch_reset(info->gpmc_cs);
}
}
@@ -363,7 +363,7 @@ static void omap_write_buf_pref(struct mtd_info *mtd,
}
/* disable and stop the PFPW engine */
- gpmc_prefetch_reset();
+ gpmc_prefetch_reset(info->gpmc_cs);
}
}
^ permalink raw reply related [flat|nested] 102+ messages in thread
* [PATCH v4 2/3] omap3 nand: cleanup virtual address usages
2010-05-27 13:24 ` [PATCH v4 1/3] omap3 gpmc: functionality enhancement Sukumar Ghorai
@ 2010-05-27 13:24 ` Sukumar Ghorai
2010-05-27 13:24 ` [PATCH v4 3/3] omap3 nand: fix issue in board file to detect nand Sukumar Ghorai
2010-05-27 18:26 ` [PATCH v4 1/3] omap3 gpmc: functionality enhancement Vimal Singh
1 sibling, 1 reply; 102+ messages in thread
From: Sukumar Ghorai @ 2010-05-27 13:24 UTC (permalink / raw)
To: linux-omap; +Cc: Sukumar Ghorai
This patch removes direct reference of gpmc address from generic nand platform code.
Nand platform code now uses wrapper functions which are implemented in gpmc module.
Signed-off-by: Sukumar Ghorai <s-ghorai@ti.com>
---
arch/arm/mach-omap2/gpmc-nand.c | 39 ++----
arch/arm/plat-omap/include/plat/gpmc.h | 5 -
arch/arm/plat-omap/include/plat/nand.h | 6 +-
drivers/mtd/nand/omap2.c | 225 +++++++++-----------------------
4 files changed, 77 insertions(+), 198 deletions(-)
diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c
index e57fb29..80f5d94
--- a/arch/arm/mach-omap2/gpmc-nand.c
+++ b/arch/arm/mach-omap2/gpmc-nand.c
@@ -19,8 +19,6 @@
#include <plat/board.h>
#include <plat/gpmc.h>
-#define WR_RD_PIN_MONITORING 0x00600000
-
static struct omap_nand_platform_data *gpmc_nand_data;
static struct resource gpmc_nand_resource = {
@@ -71,10 +69,10 @@ static int omap2_nand_gpmc_retime(void)
t.wr_cycle = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->wr_cycle);
/* Configure GPMC */
- gpmc_cs_write_reg(gpmc_nand_data->cs, GPMC_CS_CONFIG1,
- GPMC_CONFIG1_DEVICESIZE(gpmc_nand_data->devsize) |
- GPMC_CONFIG1_DEVICETYPE_NAND);
-
+ gpmc_hwcontrol(gpmc_nand_data->cs,
+ GPMC_CONFIG_DEV_SIZE, 1, gpmc_nand_data->devsize, NULL);
+ gpmc_hwcontrol(gpmc_nand_data->cs,
+ GPMC_CONFIG_DEV_TYPE, 1, GPMC_DEVICETYPE_NAND, NULL);
err = gpmc_cs_set_timings(gpmc_nand_data->cs, &t);
if (err)
return err;
@@ -82,27 +80,13 @@ static int omap2_nand_gpmc_retime(void)
return 0;
}
-static int gpmc_nand_setup(void)
-{
- struct device *dev = &gpmc_nand_device.dev;
-
- /* Set timings in GPMC */
- if (omap2_nand_gpmc_retime() < 0) {
- dev_err(dev, "Unable to set gpmc timings\n");
- return -EINVAL;
- }
-
- return 0;
-}
-
int __init gpmc_nand_init(struct omap_nand_platform_data *_nand_data)
{
- unsigned int val;
int err = 0;
struct device *dev = &gpmc_nand_device.dev;
gpmc_nand_data = _nand_data;
- gpmc_nand_data->nand_setup = gpmc_nand_setup;
+ gpmc_nand_data->nand_setup = omap2_nand_gpmc_retime;
gpmc_nand_device.dev.platform_data = gpmc_nand_data;
err = gpmc_cs_request(gpmc_nand_data->cs, NAND_IO_SIZE,
@@ -112,19 +96,17 @@ int __init gpmc_nand_init(struct omap_nand_platform_data *_nand_data)
return err;
}
- err = gpmc_nand_setup();
+ /* Set timings in GPMC */
+ err = omap2_nand_gpmc_retime();
if (err < 0) {
- dev_err(dev, "NAND platform setup failed: %d\n", err);
+ dev_err(dev, "Unable to set gpmc timings: %d\n", err);
return err;
}
/* Enable RD PIN Monitoring Reg */
if (gpmc_nand_data->dev_ready) {
- val = gpmc_cs_read_reg(gpmc_nand_data->cs,
- GPMC_CS_CONFIG1);
- val |= WR_RD_PIN_MONITORING;
- gpmc_cs_write_reg(gpmc_nand_data->cs,
- GPMC_CS_CONFIG1, val);
+ gpmc_hwcontrol(gpmc_nand_data->cs,
+ GPMC_CONFIG_RDY_BSY, 1, 1, NULL);
}
err = platform_device_register(&gpmc_nand_device);
@@ -140,3 +122,4 @@ out_free_cs:
return err;
}
+
diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h
index 8a1e9d9..ccbc530
--- a/arch/arm/plat-omap/include/plat/gpmc.h
+++ b/arch/arm/plat-omap/include/plat/gpmc.h
@@ -25,9 +25,6 @@
#define GPMC_CS_NAND_ADDRESS 0x20
#define GPMC_CS_NAND_DATA 0x24
-#define GPMC_CONFIG 0x50
-#define GPMC_STATUS 0x54
-
/* Control Commands */
#define GPMC_CONFIG_WP 0x00000001
#define GPMC_CONFIG_RDY_BSY 0x00000002
@@ -63,7 +60,6 @@
#define GPMC_CONFIG1_DEVICESIZE_16 GPMC_CONFIG1_DEVICESIZE(1)
#define GPMC_CONFIG1_DEVICETYPE(val) ((val & 3) << 10)
#define GPMC_CONFIG1_DEVICETYPE_NOR GPMC_CONFIG1_DEVICETYPE(0)
-#define GPMC_CONFIG1_DEVICETYPE_NAND GPMC_CONFIG1_DEVICETYPE(2)
#define GPMC_CONFIG1_MUXADDDATA (1 << 9)
#define GPMC_CONFIG1_TIME_PARA_GRAN (1 << 4)
#define GPMC_CONFIG1_FCLK_DIV(val) (val & 3)
@@ -133,7 +129,6 @@ extern int gpmc_cs_reserved(int cs);
extern int gpmc_prefetch_enable(int cs, int dma_mode,
unsigned int u32_count, int is_write);
extern int gpmc_prefetch_reset(int cs);
-extern int gpmc_prefetch_status(void);
extern void omap3_gpmc_save_context(void);
extern void omap3_gpmc_restore_context(void);
extern void gpmc_init(void);
diff --git a/arch/arm/plat-omap/include/plat/nand.h b/arch/arm/plat-omap/include/plat/nand.h
index f8efd54..6562cd0
--- a/arch/arm/plat-omap/include/plat/nand.h
+++ b/arch/arm/plat-omap/include/plat/nand.h
@@ -21,13 +21,11 @@ struct omap_nand_platform_data {
int (*dev_ready)(struct omap_nand_platform_data *);
int dma_channel;
unsigned long phys_base;
- void __iomem *gpmc_cs_baseaddr;
- void __iomem *gpmc_baseaddr;
int devsize;
};
-/* size (4 KiB) for IO mapping */
-#define NAND_IO_SIZE SZ_4K
+/* minimum size for IO mapping */
+#define NAND_IO_SIZE 4
#if defined(CONFIG_MTD_NAND_OMAP2) || defined(CONFIG_MTD_NAND_OMAP2_MODULE)
extern int gpmc_nand_init(struct omap_nand_platform_data *d);
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index ec8eb31..f9fa3cb
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -7,6 +7,7 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
+#define CONFIG_MTD_NAND_OMAP_HWECC
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
@@ -23,20 +24,8 @@
#include <plat/gpmc.h>
#include <plat/nand.h>
-#define GPMC_IRQ_STATUS 0x18
-#define GPMC_ECC_CONFIG 0x1F4
-#define GPMC_ECC_CONTROL 0x1F8
-#define GPMC_ECC_SIZE_CONFIG 0x1FC
-#define GPMC_ECC1_RESULT 0x200
-
#define DRIVER_NAME "omap2-nand"
-#define NAND_WP_OFF 0
-#define NAND_WP_BIT 0x00000010
-
-#define GPMC_BUF_FULL 0x00000001
-#define GPMC_BUF_EMPTY 0x00000000
-
#define NAND_Ecc_P1e (1 << 0)
#define NAND_Ecc_P2e (1 << 1)
#define NAND_Ecc_P4e (1 << 2)
@@ -139,34 +128,11 @@ struct omap_nand_info {
int gpmc_cs;
unsigned long phys_base;
- void __iomem *gpmc_cs_baseaddr;
- void __iomem *gpmc_baseaddr;
- void __iomem *nand_pref_fifo_add;
struct completion comp;
int dma_ch;
};
/**
- * omap_nand_wp - This function enable or disable the Write Protect feature
- * @mtd: MTD device structure
- * @mode: WP ON/OFF
- */
-static void omap_nand_wp(struct mtd_info *mtd, int mode)
-{
- struct omap_nand_info *info = container_of(mtd,
- struct omap_nand_info, mtd);
-
- unsigned long config = __raw_readl(info->gpmc_baseaddr + GPMC_CONFIG);
-
- if (mode)
- config &= ~(NAND_WP_BIT); /* WP is ON */
- else
- config |= (NAND_WP_BIT); /* WP is OFF */
-
- __raw_writel(config, (info->gpmc_baseaddr + GPMC_CONFIG));
-}
-
-/**
* omap_hwcontrol - hardware specific access to control-lines
* @mtd: MTD device structure
* @cmd: command to device
@@ -181,31 +147,20 @@ static void omap_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
struct omap_nand_info *info = container_of(mtd,
struct omap_nand_info, mtd);
- switch (ctrl) {
- case NAND_CTRL_CHANGE | NAND_CTRL_CLE:
- info->nand.IO_ADDR_W = info->gpmc_cs_baseaddr +
- GPMC_CS_NAND_COMMAND;
- info->nand.IO_ADDR_R = info->gpmc_cs_baseaddr +
- GPMC_CS_NAND_DATA;
- break;
-
- case NAND_CTRL_CHANGE | NAND_CTRL_ALE:
- info->nand.IO_ADDR_W = info->gpmc_cs_baseaddr +
- GPMC_CS_NAND_ADDRESS;
- info->nand.IO_ADDR_R = info->gpmc_cs_baseaddr +
- GPMC_CS_NAND_DATA;
- break;
-
- case NAND_CTRL_CHANGE | NAND_NCE:
- info->nand.IO_ADDR_W = info->gpmc_cs_baseaddr +
- GPMC_CS_NAND_DATA;
- info->nand.IO_ADDR_R = info->gpmc_cs_baseaddr +
- GPMC_CS_NAND_DATA;
- break;
- }
- if (cmd != NAND_CMD_NONE)
- __raw_writeb(cmd, info->nand.IO_ADDR_W);
+ if (cmd != NAND_CMD_NONE) {
+ if (ctrl & NAND_CLE)
+ gpmc_hwcontrol(info->gpmc_cs,
+ GPMC_NAND_COMMAND, 1, cmd, NULL);
+
+ else if (ctrl & NAND_ALE)
+ gpmc_hwcontrol(info->gpmc_cs,
+ GPMC_NAND_ADDRESS, 1, cmd, NULL);
+
+ else /* NAND_NCE */
+ gpmc_hwcontrol(info->gpmc_cs,
+ GPMC_NAND_DATA, 1, cmd, NULL);
+ }
}
/**
@@ -232,11 +187,15 @@ static void omap_write_buf8(struct mtd_info *mtd, const u_char *buf, int len)
struct omap_nand_info *info = container_of(mtd,
struct omap_nand_info, mtd);
u_char *p = (u_char *)buf;
+ u32 status = 0;
while (len--) {
iowrite8(*p++, info->nand.IO_ADDR_W);
- while (GPMC_BUF_EMPTY == (readl(info->gpmc_baseaddr +
- GPMC_STATUS) & GPMC_BUF_FULL));
+ /* wait until buffer is available for write */
+ do {
+ gpmc_hwcontrol(info->gpmc_cs,
+ GPMC_STATUS_BUFFER, 0, 0, &status);
+ } while (!status);
}
}
@@ -264,16 +223,17 @@ static void omap_write_buf16(struct mtd_info *mtd, const u_char * buf, int len)
struct omap_nand_info *info = container_of(mtd,
struct omap_nand_info, mtd);
u16 *p = (u16 *) buf;
-
+ u32 status = 0;
/* FIXME try bursts of writesw() or DMA ... */
len >>= 1;
while (len--) {
iowrite16(*p++, info->nand.IO_ADDR_W);
-
- while (GPMC_BUF_EMPTY == (readl(info->gpmc_baseaddr +
- GPMC_STATUS) & GPMC_BUF_FULL))
- ;
+ /* wait until buffer is available for write */
+ do {
+ gpmc_hwcontrol(info->gpmc_cs,
+ GPMC_STATUS_BUFFER, 0, 0, &status);
+ } while (!status);
}
}
@@ -287,7 +247,7 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len)
{
struct omap_nand_info *info = container_of(mtd,
struct omap_nand_info, mtd);
- uint32_t pfpw_status = 0, r_count = 0;
+ uint32_t r_count = 0;
int ret = 0;
u32 *p = (u32 *)buf;
@@ -310,14 +270,15 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len)
else
omap_read_buf8(mtd, buf, len);
} else {
+ p = (u32 *) buf;
do {
- pfpw_status = gpmc_prefetch_status();
- r_count = ((pfpw_status >> 24) & 0x7F) >> 2;
- ioread32_rep(info->nand_pref_fifo_add, p, r_count);
+ gpmc_hwcontrol(info->gpmc_cs,
+ GPMC_PREFETCH_FIFO_CNT, 0, 0, &r_count);
+ r_count = r_count >> 2;
+ ioread32_rep(info->nand.IO_ADDR_R, p, r_count);
p += r_count;
len -= r_count << 2;
} while (len);
-
/* disable and stop the PFPW engine */
gpmc_prefetch_reset(info->gpmc_cs);
}
@@ -334,13 +295,13 @@ static void omap_write_buf_pref(struct mtd_info *mtd,
{
struct omap_nand_info *info = container_of(mtd,
struct omap_nand_info, mtd);
- uint32_t pfpw_status = 0, w_count = 0;
+ uint32_t pref_count = 0, w_count = 0;
int i = 0, ret = 0;
- u16 *p = (u16 *) buf;
+ u16 *p;
/* take care of subpage writes */
if (len % 2 != 0) {
- writeb(*buf, info->nand.IO_ADDR_R);
+ writeb(*buf, info->nand.IO_ADDR_W);
p = (u16 *)(buf + 1);
len--;
}
@@ -354,14 +315,19 @@ static void omap_write_buf_pref(struct mtd_info *mtd,
else
omap_write_buf8(mtd, buf, len);
} else {
- pfpw_status = gpmc_prefetch_status();
- while (pfpw_status & 0x3FFF) {
- w_count = ((pfpw_status >> 24) & 0x7F) >> 1;
+ p = (u16 *) buf;
+ while (len) {
+ gpmc_hwcontrol(info->gpmc_cs,
+ GPMC_PREFETCH_FIFO_CNT, 0, 0, &w_count);
+ w_count = w_count >> 1;
for (i = 0; (i < w_count) && len; i++, len -= 2)
- iowrite16(*p++, info->nand_pref_fifo_add);
- pfpw_status = gpmc_prefetch_status();
+ iowrite16(*p++, info->nand.IO_ADDR_W);
}
-
+ /* wait for data to flushed-out before reset the prefetch */
+ do {
+ gpmc_hwcontrol(info->gpmc_cs,
+ GPMC_PREFETCH_COUNT, 0, 0, &pref_count);
+ } while (pref_count);
/* disable and stop the PFPW engine */
gpmc_prefetch_reset(info->gpmc_cs);
}
@@ -451,8 +417,10 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr,
/* setup and start DMA using dma_addr */
wait_for_completion(&info->comp);
- while (0x3fff & (prefetch_status = gpmc_prefetch_status()))
- ;
+ do {
+ gpmc_hwcontrol(info->gpmc_cs,
+ GPMC_PREFETCH_COUNT, 0, 0, &prefetch_status);
+ } while (prefetch_status);
/* disable and stop the PFPW engine */
gpmc_prefetch_reset();
@@ -530,29 +498,6 @@ static int omap_verify_buf(struct mtd_info *mtd, const u_char * buf, int len)
}
#ifdef CONFIG_MTD_NAND_OMAP_HWECC
-/**
- * omap_hwecc_init - Initialize the HW ECC for NAND flash in GPMC controller
- * @mtd: MTD device structure
- */
-static void omap_hwecc_init(struct mtd_info *mtd)
-{
- struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
- mtd);
- struct nand_chip *chip = mtd->priv;
- unsigned long val = 0x0;
-
- /* Read from ECC Control Register */
- val = __raw_readl(info->gpmc_baseaddr + GPMC_ECC_CONTROL);
- /* Clear all ECC | Enable Reg1 */
- val = ((0x00000001<<8) | 0x00000001);
- __raw_writel(val, info->gpmc_baseaddr + GPMC_ECC_CONTROL);
-
- /* Read from ECC Size Config Register */
- val = __raw_readl(info->gpmc_baseaddr + GPMC_ECC_SIZE_CONFIG);
- /* ECCSIZE1=512 | Select eccResultsize[0-3] */
- val = ((((chip->ecc.size >> 1) - 1) << 22) | (0x0000000F));
- __raw_writel(val, info->gpmc_baseaddr + GPMC_ECC_SIZE_CONFIG);
-}
/**
* gen_true_ecc - This function will generate true ECC value
@@ -755,19 +700,7 @@ static int omap_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
{
struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
mtd);
- unsigned long val = 0x0;
- unsigned long reg;
-
- /* Start Reading from HW ECC1_Result = 0x200 */
- reg = (unsigned long)(info->gpmc_baseaddr + GPMC_ECC1_RESULT);
- val = __raw_readl(reg);
- *ecc_code++ = val; /* P128e, ..., P1e */
- *ecc_code++ = val >> 16; /* P128o, ..., P1o */
- /* P2048o, P1024o, P512o, P256o, P2048e, P1024e, P512e, P256e */
- *ecc_code++ = ((val >> 8) & 0x0f) | ((val >> 20) & 0xf0);
- reg += 4;
-
- return 0;
+ return gpmc_calculate_ecc(info->gpmc_cs, dat, ecc_code);
}
/**
@@ -781,32 +714,10 @@ static void omap_enable_hwecc(struct mtd_info *mtd, int mode)
mtd);
struct nand_chip *chip = mtd->priv;
unsigned int dev_width = (chip->options & NAND_BUSWIDTH_16) ? 1 : 0;
- unsigned long val = __raw_readl(info->gpmc_baseaddr + GPMC_ECC_CONFIG);
-
- switch (mode) {
- case NAND_ECC_READ:
- __raw_writel(0x101, info->gpmc_baseaddr + GPMC_ECC_CONTROL);
- /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */
- val = (dev_width << 7) | (info->gpmc_cs << 1) | (0x1);
- break;
- case NAND_ECC_READSYN:
- __raw_writel(0x100, info->gpmc_baseaddr + GPMC_ECC_CONTROL);
- /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */
- val = (dev_width << 7) | (info->gpmc_cs << 1) | (0x1);
- break;
- case NAND_ECC_WRITE:
- __raw_writel(0x101, info->gpmc_baseaddr + GPMC_ECC_CONTROL);
- /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */
- val = (dev_width << 7) | (info->gpmc_cs << 1) | (0x1);
- break;
- default:
- DEBUG(MTD_DEBUG_LEVEL0, "Error: Unrecognized Mode[%d]!\n",
- mode);
- break;
- }
- __raw_writel(val, info->gpmc_baseaddr + GPMC_ECC_CONFIG);
+ gpmc_enable_hwecc(info->gpmc_cs, mode, dev_width, info->nand.ecc.size);
}
+
#endif
/**
@@ -834,14 +745,10 @@ static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip)
else
timeo += (HZ * 20) / 1000;
- this->IO_ADDR_W = (void *) info->gpmc_cs_baseaddr +
- GPMC_CS_NAND_COMMAND;
- this->IO_ADDR_R = (void *) info->gpmc_cs_baseaddr + GPMC_CS_NAND_DATA;
-
- __raw_writeb(NAND_CMD_STATUS & 0xFF, this->IO_ADDR_W);
-
+ gpmc_hwcontrol(info->gpmc_cs,
+ GPMC_NAND_COMMAND, 1, (NAND_CMD_STATUS & 0xFF), NULL);
while (time_before(jiffies, timeo)) {
- status = __raw_readb(this->IO_ADDR_R);
+ gpmc_hwcontrol(info->gpmc_cs, GPMC_NAND_DATA, 0, 0, &status);
if (status & NAND_STATUS_READY)
break;
cond_resched();
@@ -855,22 +762,24 @@ static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip)
*/
static int omap_dev_ready(struct mtd_info *mtd)
{
+ unsigned int val = 0;
struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
mtd);
- unsigned int val = __raw_readl(info->gpmc_baseaddr + GPMC_IRQ_STATUS);
+ gpmc_hwcontrol(info->gpmc_cs, GPMC_GET_SET_IRQ_STATUS, 0, 0, &val);
if ((val & 0x100) == 0x100) {
/* Clear IRQ Interrupt */
val |= 0x100;
val &= ~(0x0);
- __raw_writel(val, info->gpmc_baseaddr + GPMC_IRQ_STATUS);
+ gpmc_hwcontrol(info->gpmc_cs,
+ GPMC_GET_SET_IRQ_STATUS, 1, val, NULL);
} else {
unsigned int cnt = 0;
while (cnt++ < 0x1FF) {
if ((val & 0x100) == 0x100)
return 0;
- val = __raw_readl(info->gpmc_baseaddr +
- GPMC_IRQ_STATUS);
+ gpmc_hwcontrol(info->gpmc_cs,
+ GPMC_GET_SET_IRQ_STATUS, 0, 0, &val);
}
}
@@ -901,8 +810,6 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
info->pdev = pdev;
info->gpmc_cs = pdata->cs;
- info->gpmc_baseaddr = pdata->gpmc_baseaddr;
- info->gpmc_cs_baseaddr = pdata->gpmc_cs_baseaddr;
info->phys_base = pdata->phys_base;
info->mtd.priv = &info->nand;
@@ -913,7 +820,7 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
info->nand.options |= NAND_SKIP_BBTSCAN;
/* NAND write protect off */
- omap_nand_wp(&info->mtd, NAND_WP_OFF);
+ gpmc_hwcontrol(info->gpmc_cs, GPMC_CONFIG_WP, 1, 0, NULL);
if (!request_mem_region(info->phys_base, NAND_IO_SIZE,
pdev->dev.driver->name)) {
@@ -948,8 +855,6 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
}
if (use_prefetch) {
- /* copy the virtual address of nand base for fifo access */
- info->nand_pref_fifo_add = info->nand.IO_ADDR_R;
info->nand.read_buf = omap_read_buf_pref;
info->nand.write_buf = omap_write_buf_pref;
@@ -989,8 +894,6 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
info->nand.ecc.correct = omap_correct_data;
info->nand.ecc.mode = NAND_ECC_HW;
- /* init HW ECC */
- omap_hwecc_init(&info->mtd);
#else
info->nand.ecc.mode = NAND_ECC_SOFT;
#endif
@@ -1040,7 +943,7 @@ static int omap_nand_remove(struct platform_device *pdev)
/* Release NAND device, its internal structures and partitions */
nand_release(&info->mtd);
- iounmap(info->nand_pref_fifo_add);
+ iounmap(info->nand.IO_ADDR_R);
kfree(&info->mtd);
return 0;
}
^ permalink raw reply related [flat|nested] 102+ messages in thread
* [PATCH v4 3/3] omap3 nand: fix issue in board file to detect nand
2010-05-27 13:24 ` [PATCH v4 2/3] omap3 nand: cleanup virtual address usages Sukumar Ghorai
@ 2010-05-27 13:24 ` Sukumar Ghorai
0 siblings, 0 replies; 102+ messages in thread
From: Sukumar Ghorai @ 2010-05-27 13:24 UTC (permalink / raw)
To: linux-omap; +Cc: Sukumar Ghorai
Board file modified for not to provide gpmc phys_base address to nand driver.
The gpmc_nand_init funciton is now used to detect the nand and required to
adopt _prob function as in nand/omap2.c
Signed-off-by: Sukumar Ghorai <s-ghorai@ti.com>
---
arch/arm/mach-omap2/board-cm-t35.c | 20 +-------------------
arch/arm/mach-omap2/board-devkit8000.c | 25 +------------------------
arch/arm/mach-omap2/board-omap3beagle.c | 24 +-----------------------
arch/arm/mach-omap2/board-omap3touchbook.c | 25 +------------------------
arch/arm/mach-omap2/board-overo.c | 24 +-----------------------
5 files changed, 5 insertions(+), 113 deletions(-)
diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c
index e679a2c..0544294
--- a/arch/arm/mach-omap2/board-cm-t35.c
+++ b/arch/arm/mach-omap2/board-cm-t35.c
@@ -61,8 +61,6 @@
#define SB_T35_SMSC911X_GPIO 65
#define NAND_BLOCK_SIZE SZ_128K
-#define GPMC_CS0_BASE 0x60
-#define GPMC_CS0_BASE_ADDR (OMAP34XX_GPMC_VIRT + GPMC_CS0_BASE)
#if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
#include <linux/smsc911x.h>
@@ -223,28 +221,12 @@ static struct omap_nand_platform_data cm_t35_nand_data = {
.nr_parts = ARRAY_SIZE(cm_t35_nand_partitions),
.dma_channel = -1, /* disable DMA in OMAP NAND driver */
.cs = 0,
- .gpmc_cs_baseaddr = (void __iomem *)GPMC_CS0_BASE_ADDR,
- .gpmc_baseaddr = (void __iomem *)OMAP34XX_GPMC_VIRT,
};
-static struct resource cm_t35_nand_resource = {
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device cm_t35_nand_device = {
- .name = "omap2-nand",
- .id = -1,
- .num_resources = 1,
- .resource = &cm_t35_nand_resource,
- .dev = {
- .platform_data = &cm_t35_nand_data,
- },
-};
-
static void __init cm_t35_init_nand(void)
{
- if (platform_device_register(&cm_t35_nand_device) < 0)
+ if (gpmc_nand_init(&cm_t35_nand_data) < 0)
pr_err("CM-T35: Unable to register NAND device\n");
}
#else
diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c
index 77022b5..9a8135d
--- a/arch/arm/mach-omap2/board-devkit8000.c
+++ b/arch/arm/mach-omap2/board-devkit8000.c
@@ -58,9 +58,6 @@
#include "mux.h"
#include "hsmmc.h"
-#define GPMC_CS0_BASE 0x60
-#define GPMC_CS_SIZE 0x30
-
#define NAND_BLOCK_SIZE SZ_128K
#define OMAP_DM9000_GPIO_IRQ 25
@@ -104,20 +101,6 @@ static struct omap_nand_platform_data devkit8000_nand_data = {
.dma_channel = -1, /* disable DMA in OMAP NAND driver */
};
-static struct resource devkit8000_nand_resource = {
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device devkit8000_nand_device = {
- .name = "omap2-nand",
- .id = -1,
- .dev = {
- .platform_data = &devkit8000_nand_data,
- },
- .num_resources = 1,
- .resource = &devkit8000_nand_resource,
-};
-
static struct omap2_hsmmc_info mmc[] = {
{
.mmc = 1,
@@ -581,8 +564,6 @@ static void __init devkit8000_flash_init(void)
u8 cs = 0;
u8 nandcs = GPMC_CS_NUM + 1;
- u32 gpmc_base_add = OMAP34XX_GPMC_VIRT;
-
/* find out the chip-select on which NAND exists */
while (cs < GPMC_CS_NUM) {
u32 ret = 0;
@@ -604,13 +585,9 @@ static void __init devkit8000_flash_init(void)
if (nandcs < GPMC_CS_NUM) {
devkit8000_nand_data.cs = nandcs;
- devkit8000_nand_data.gpmc_cs_baseaddr = (void *)
- (gpmc_base_add + GPMC_CS0_BASE + nandcs * GPMC_CS_SIZE);
- devkit8000_nand_data.gpmc_baseaddr = (void *)
- (gpmc_base_add);
printk(KERN_INFO "Registering NAND on CS%d\n", nandcs);
- if (platform_device_register(&devkit8000_nand_device) < 0)
+ if (gpmc_nand_init(&devkit8000_nand_data) < 0)
printk(KERN_ERR "Unable to register NAND device\n");
}
}
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index 69b154c..dc5a7e8
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -48,9 +48,6 @@
#include "mux.h"
#include "hsmmc.h"
-#define GPMC_CS0_BASE 0x60
-#define GPMC_CS_SIZE 0x30
-
#define NAND_BLOCK_SIZE SZ_128K
static struct mtd_partition omap3beagle_nand_partitions[] = {
@@ -93,20 +90,6 @@ static struct omap_nand_platform_data omap3beagle_nand_data = {
.dev_ready = NULL,
};
-static struct resource omap3beagle_nand_resource = {
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device omap3beagle_nand_device = {
- .name = "omap2-nand",
- .id = -1,
- .dev = {
- .platform_data = &omap3beagle_nand_data,
- },
- .num_resources = 1,
- .resource = &omap3beagle_nand_resource,
-};
-
/* DSS */
static int beagle_enable_dvi(struct omap_dss_device *dssdev)
@@ -424,8 +407,6 @@ static void __init omap3beagle_flash_init(void)
u8 cs = 0;
u8 nandcs = GPMC_CS_NUM + 1;
- u32 gpmc_base_add = OMAP34XX_GPMC_VIRT;
-
/* find out the chip-select on which NAND exists */
while (cs < GPMC_CS_NUM) {
u32 ret = 0;
@@ -447,12 +428,9 @@ static void __init omap3beagle_flash_init(void)
if (nandcs < GPMC_CS_NUM) {
omap3beagle_nand_data.cs = nandcs;
- omap3beagle_nand_data.gpmc_cs_baseaddr = (void *)
- (gpmc_base_add + GPMC_CS0_BASE + nandcs * GPMC_CS_SIZE);
- omap3beagle_nand_data.gpmc_baseaddr = (void *) (gpmc_base_add);
printk(KERN_INFO "Registering NAND on CS%d\n", nandcs);
- if (platform_device_register(&omap3beagle_nand_device) < 0)
+ if (gpmc_nand_init(&omap3beagle_nand_data) < 0)
printk(KERN_ERR "Unable to register NAND device\n");
}
}
diff --git a/arch/arm/mach-omap2/board-omap3touchbook.c b/arch/arm/mach-omap2/board-omap3touchbook.c
index 2504d41..e8ad30c
--- a/arch/arm/mach-omap2/board-omap3touchbook.c
+++ b/arch/arm/mach-omap2/board-omap3touchbook.c
@@ -54,9 +54,6 @@
#include <asm/setup.h>
-#define GPMC_CS0_BASE 0x60
-#define GPMC_CS_SIZE 0x30
-
#define NAND_BLOCK_SIZE SZ_128K
#define OMAP3_AC_GPIO 136
@@ -106,20 +103,6 @@ static struct omap_nand_platform_data omap3touchbook_nand_data = {
.dev_ready = NULL,
};
-static struct resource omap3touchbook_nand_resource = {
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device omap3touchbook_nand_device = {
- .name = "omap2-nand",
- .id = -1,
- .dev = {
- .platform_data = &omap3touchbook_nand_data,
- },
- .num_resources = 1,
- .resource = &omap3touchbook_nand_resource,
-};
-
#include "sdram-micron-mt46h32m32lf-6.h"
static struct omap2_hsmmc_info mmc[] = {
@@ -459,8 +442,6 @@ static void __init omap3touchbook_flash_init(void)
u8 cs = 0;
u8 nandcs = GPMC_CS_NUM + 1;
- u32 gpmc_base_add = OMAP34XX_GPMC_VIRT;
-
/* find out the chip-select on which NAND exists */
while (cs < GPMC_CS_NUM) {
u32 ret = 0;
@@ -482,13 +463,9 @@ static void __init omap3touchbook_flash_init(void)
if (nandcs < GPMC_CS_NUM) {
omap3touchbook_nand_data.cs = nandcs;
- omap3touchbook_nand_data.gpmc_cs_baseaddr = (void *)
- (gpmc_base_add + GPMC_CS0_BASE + nandcs * GPMC_CS_SIZE);
- omap3touchbook_nand_data.gpmc_baseaddr =
- (void *) (gpmc_base_add);
printk(KERN_INFO "Registering NAND on CS%d\n", nandcs);
- if (platform_device_register(&omap3touchbook_nand_device) < 0)
+ if (gpmc_nand_init(&omap3touchbook_nand_data) < 0)
printk(KERN_ERR "Unable to register NAND device\n");
}
}
diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
index 79ac414..cddc7ad
--- a/arch/arm/mach-omap2/board-overo.c
+++ b/arch/arm/mach-omap2/board-overo.c
@@ -58,8 +58,6 @@
#define OVERO_GPIO_USBH_NRESET 183
#define NAND_BLOCK_SIZE SZ_128K
-#define GPMC_CS0_BASE 0x60
-#define GPMC_CS_SIZE 0x30
#define OVERO_SMSC911X_CS 5
#define OVERO_SMSC911X_GPIO 176
@@ -231,28 +229,11 @@ static struct omap_nand_platform_data overo_nand_data = {
.dma_channel = -1, /* disable DMA in OMAP NAND driver */
};
-static struct resource overo_nand_resource = {
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device overo_nand_device = {
- .name = "omap2-nand",
- .id = -1,
- .dev = {
- .platform_data = &overo_nand_data,
- },
- .num_resources = 1,
- .resource = &overo_nand_resource,
-};
-
-
static void __init overo_flash_init(void)
{
u8 cs = 0;
u8 nandcs = GPMC_CS_NUM + 1;
- u32 gpmc_base_add = OMAP34XX_GPMC_VIRT;
-
/* find out the chip-select on which NAND exists */
while (cs < GPMC_CS_NUM) {
u32 ret = 0;
@@ -274,12 +255,9 @@ static void __init overo_flash_init(void)
if (nandcs < GPMC_CS_NUM) {
overo_nand_data.cs = nandcs;
- overo_nand_data.gpmc_cs_baseaddr = (void *)
- (gpmc_base_add + GPMC_CS0_BASE + nandcs * GPMC_CS_SIZE);
- overo_nand_data.gpmc_baseaddr = (void *) (gpmc_base_add);
printk(KERN_INFO "Registering NAND on CS%d\n", nandcs);
- if (platform_device_register(&overo_nand_device) < 0)
+ if (gpmc_nand_init(&overo_nand_data) < 0)
printk(KERN_ERR "Unable to register NAND device\n");
}
}
^ permalink raw reply related [flat|nested] 102+ messages in thread
* Re: [PATCH v4 1/3] omap3 gpmc: functionality enhancement
2010-05-27 13:24 ` [PATCH v4 1/3] omap3 gpmc: functionality enhancement Sukumar Ghorai
2010-05-27 13:24 ` [PATCH v4 2/3] omap3 nand: cleanup virtual address usages Sukumar Ghorai
@ 2010-05-27 18:26 ` Vimal Singh
1 sibling, 0 replies; 102+ messages in thread
From: Vimal Singh @ 2010-05-27 18:26 UTC (permalink / raw)
To: Sukumar Ghorai; +Cc: linux-omap
On Thu, May 27, 2010 at 6:54 PM, Sukumar Ghorai <s-ghorai@ti.com> wrote:
[...]
> -static unsigned gpmc_cs_map;
> +static unsigned int gpmc_cs_map; /* flag for cs which are initialized */
Tab should be after 'int', not before.
[...]
> @@ -456,13 +565,22 @@ EXPORT_SYMBOL(gpmc_prefetch_enable);
> /**
> * gpmc_prefetch_reset - disables and stops the prefetch engine
> */
> -void gpmc_prefetch_reset(void)
> +int gpmc_prefetch_reset(int cs)
> {
> + u32 config1;
> +
> + /* check if the same module/cs is trying to reset */
> + config1 = gpmc_read_reg(GPMC_PREFETCH_CONFIG1);
> + if (((config1 >> CS_NUM_SHIFT) & 0x7) != cs)
> + return -EINVAL;
> +
You really do not need this.
Prefetch has just one instance at a time and 'reset' will be call only
when driver has got access to prefetch (for either read or write
access), from the driver.
--
Regards,
Vimal Singh
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 102+ messages in thread
* RE: [PATCH] nand support on omap3 boards
2010-04-13 17:37 ` [PATCH] nand support on omap3 boards Sukumar Ghorai
` (2 preceding siblings ...)
2010-05-04 6:01 ` Ghorai, Sukumar
@ 2010-05-28 13:48 ` Ghorai, Sukumar
3 siblings, 0 replies; 102+ messages in thread
From: Ghorai, Sukumar @ 2010-05-28 13:48 UTC (permalink / raw)
To: Tony Lindgren, Vimal Singh; +Cc: linux-omap@vger.kernel.org
Hello Tony,
I need your comment/input - whether we need an additional file for NAND support in ZOOM2/3?
In current codebase has a board-sdp-flash.c file. I think we can remove "-sdp-" from board-sdp-flash.c and reuse the file for ZOOM boards or any other upcoming board(s).
Advantage:
a. No need to add any additional file like board-zoom-flash.c
b. And the existing board-sdp-flash.c is very small and easily re-use for zoom boards easily.
Disadvantage:
a. Few additional functions in the same file for NOR and OneNAND is not applicable for zoom.
b. rename the file board-sdp-flash.c to board-flash.c
c. Remove the static of board_nand_init() and additional one line for zoom board checking.
Please let me know your opinion.
Regards,
Ghorai
> -----Original Message-----
> From: Ghorai, Sukumar
> Sent: Tuesday, April 13, 2010 11:07 PM
> To: linux-omap@vger.kernel.org
> Cc: Ghorai, Sukumar
> Subject: [PATCH] nand support on omap3 boards
>
> The following set of patches applies on top of the Tony's master
> branch.
> And these are the patches required to enable nand (nor and onenand for
> sdp
> only) for different platform.
>
> Sukumar Ghorai (3):
> OMAP: ZOOM: Introducing 'board-zoom-flash.c'
> omap3: add support for NAND on zoom2 board
> omap3: add support for NAND on zoom3 board
> omap-3630-sdp : Add support for Flash
> omap-3630-sdp: enable Flash device support
> omap3: add support for NAND on LDP board
> zoom2: enable NAND support
> zoom3: enable NAND support
>
> arch/arm/configs/omap_3630sdp_defconfig | 77 +++++++++++++++++-
> arch/arm/configs/omap_zoom2_defconfig | 90
> ++++++++++++++++++++-
> arch/arm/configs/omap_zoom3_defconfig | 90
> ++++++++++++++++++++-
> arch/arm/mach-omap2/Makefile | 4 +
> arch/arm/mach-omap2/board-3630sdp.c | 110
> +++++++++++++++++++++++++
> arch/arm/mach-omap2/board-ldp.c | 41 +++++++++
> arch/arm/mach-omap2/board-sdp-flash.c | 2 +
> arch/arm/mach-omap2/board-zoom-flash.c | 82 ++++++++++++++++++
> arch/arm/mach-omap2/board-zoom2.c | 49 +++++++++++
> arch/arm/mach-omap2/board-zoom3.c | 48 +++++++++++
> arch/arm/mach-omap2/include/mach/board-zoom.h | 11 +++
> 11 files changed, 601 insertions(+), 3 deletions(-) create mode 100644
> arch/arm/mach-omap2/board-zoom-flash.c
^ permalink raw reply [flat|nested] 102+ messages in thread
* [PATCH v5 0/3] omap3 nand: cleanup exiting platform related code
[not found] <Sukumar Ghorai <s-ghorai@ti.com>
` (13 preceding siblings ...)
2010-05-27 13:24 ` [PATCH v4 0/3] omap3 nand: cleanup exiting platform related code Sukumar Ghorai
@ 2010-06-04 7:40 ` Sukumar Ghorai
2010-06-04 7:40 ` [PATCH v5 1/3] omap3 gpmc: functionality enhancement Sukumar Ghorai
2010-06-08 17:12 ` [PATCH v5 0/3] omap3 nand: cleanup exiting platform related code Vimal Singh
2010-06-16 11:39 ` [PATCH v3 0/8] nand support on omap3 boards Sukumar Ghorai
15 siblings, 2 replies; 102+ messages in thread
From: Sukumar Ghorai @ 2010-06-04 7:40 UTC (permalink / raw)
To: linux-omap; +Cc: linux-mtd, tony, mike, Sukumar Ghorai
The following set of patches applies on top of for-next branch.
http://git.kernel.org/?p=linux/kernel/git/tmlind/linux-omap-2.6.git
Patches verified on: omap3430-SDP, omap3630-sdp, zoom3 and beagle board
And these are the patches required to address the following input -
1. The NAND driver needs to stop tinkering with the GPMC registers
The omap General Purpose Memory Controller (GPMC) registers are omap
specific, and not driver specific. Tinkering with these registers can
cause issues with the other devices on the GPMC.
2. Passing hardcoded GPMC_CS0_BASE needs to go from the board files
Passing hardcoded GPMC virtual addressess is sure way to mess up things.
This should all become unnecessary once the NAND drivers stops messing
with the GPMC registers directly.
Discussion: http://www.mail-archive.com/linux-omap@vger.kernel.org/msg27630.html
Changes in this series -
Unused function removed.
Functions related to ecc and prefetch engine are optimized.
v4: http://www.mail-archive.com/linux-omap@vger.kernel.org/msg29458.html
Few functionality was missing like - There should be some locking as only
one chipselect can use the ECC or prefetch engine at a time. If you have
NAND in two chipselects, bad things would happen.
v3: http://www.mail-archive.com/linux-omap@vger.kernel.org/msg28715.html
Additionally, it was needed to implement more functions for the platform
init code to use.
v2: http://www.mail-archive.com/linux-omap@vger.kernel.org/msg28467.html
v1: http://www.mail-archive.com/linux-omap@vger.kernel.org/msg28164.html
Sukumar Ghorai (3):
omap3 gpmc: functionality enhancement
omap3 nand: cleanup virtual address usages
omap3 nand: fix issue in board file to detect nand
arch/arm/mach-omap2/board-cm-t35.c | 20 +---
arch/arm/mach-omap2/board-devkit8000.c | 25 +---
arch/arm/mach-omap2/board-omap3beagle.c | 24 +---
arch/arm/mach-omap2/board-omap3touchbook.c | 25 +---
arch/arm/mach-omap2/board-overo.c | 24 +---
arch/arm/mach-omap2/board-sdp-flash.c | 5 -
arch/arm/mach-omap2/gpmc-nand.c | 39 ++----
arch/arm/mach-omap2/gpmc.c | 228 +++++++++++++++++++++++++---
arch/arm/plat-omap/include/plat/gpmc.h | 36 ++++-
arch/arm/plat-omap/include/plat/nand.h | 6 +-
drivers/mtd/nand/omap2.c | 229 ++++++++--------------------
11 files changed, 320 insertions(+), 341 deletions(-)
^ permalink raw reply [flat|nested] 102+ messages in thread
* [PATCH v5 1/3] omap3 gpmc: functionality enhancement
2010-06-04 7:40 ` [PATCH v5 0/3] omap3 nand: cleanup exiting platform related code Sukumar Ghorai
@ 2010-06-04 7:40 ` Sukumar Ghorai
2010-06-04 7:40 ` [PATCH v5 2/3] omap3 nand: cleanup virtual address usages Sukumar Ghorai
2010-07-07 10:18 ` [PATCH v5 1/3] omap3 gpmc: functionality enhancement Tony Lindgren
2010-06-08 17:12 ` [PATCH v5 0/3] omap3 nand: cleanup exiting platform related code Vimal Singh
1 sibling, 2 replies; 102+ messages in thread
From: Sukumar Ghorai @ 2010-06-04 7:40 UTC (permalink / raw)
To: linux-omap; +Cc: linux-mtd, tony, mike, Sukumar Ghorai
few functions added in gpmc module and to be used by other drivers like NAND.
E.g.: - ioctl function
- ecc functions
Signed-off-by: Sukumar Ghorai <s-ghorai@ti.com>
---
arch/arm/mach-omap2/gpmc.c | 219 ++++++++++++++++++++++++++++++--
arch/arm/plat-omap/include/plat/gpmc.h | 33 +++++-
drivers/mtd/nand/omap2.c | 4 +-
3 files changed, 239 insertions(+), 17 deletions(-)
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index 5bc3ca0..48b5af0
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -46,8 +46,9 @@
#define GPMC_ECC_CONFIG 0x1f4
#define GPMC_ECC_CONTROL 0x1f8
#define GPMC_ECC_SIZE_CONFIG 0x1fc
+#define GPMC_ECC1_RESULT 0x200
-#define GPMC_CS0 0x60
+#define GPMC_CS0_BASE 0x60
#define GPMC_CS_SIZE 0x30
#define GPMC_MEM_START 0x00000000
@@ -92,7 +93,8 @@ struct omap3_gpmc_regs {
static struct resource gpmc_mem_root;
static struct resource gpmc_cs_mem[GPMC_CS_NUM];
static DEFINE_SPINLOCK(gpmc_mem_lock);
-static unsigned gpmc_cs_map;
+static unsigned int gpmc_cs_map; /* flag for cs which are initialized */
+static int gpmc_ecc_used = -EINVAL; /* cs using ecc engine */
static void __iomem *gpmc_base;
@@ -108,11 +110,27 @@ static u32 gpmc_read_reg(int idx)
return __raw_readl(gpmc_base + idx);
}
+static void gpmc_cs_write_byte(int cs, int idx, u8 val)
+{
+ void __iomem *reg_addr;
+
+ reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx;
+ __raw_writeb(val, reg_addr);
+}
+
+static u8 gpmc_cs_read_byte(int cs, int idx)
+{
+ void __iomem *reg_addr;
+
+ reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx;
+ return __raw_readb(reg_addr);
+}
+
void gpmc_cs_write_reg(int cs, int idx, u32 val)
{
void __iomem *reg_addr;
- reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx;
+ reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx;
__raw_writel(val, reg_addr);
}
@@ -120,7 +138,7 @@ u32 gpmc_cs_read_reg(int cs, int idx)
{
void __iomem *reg_addr;
- reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx;
+ reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx;
return __raw_readl(reg_addr);
}
@@ -419,8 +437,100 @@ void gpmc_cs_free(int cs)
EXPORT_SYMBOL(gpmc_cs_free);
/**
+ * gpmc_hwcontrol - hardware specific access (read/ write) control
+ * @cs: chip select number
+ * @cmd: command type
+ * @write: 1 for write; 0 for read
+ * @wval: value to write
+ * @rval: read pointer
+ */
+int gpmc_hwcontrol(int cs, int cmd, int write, int wval, int *rval)
+{
+ u32 regval = 0;
+
+ if (!write && !rval)
+ return -EINVAL;
+
+ switch (cmd) {
+ case GPMC_STATUS_BUFFER:
+ regval = gpmc_read_reg(GPMC_STATUS);
+ /* 1 : buffer is available to write */
+ *rval = regval & GPMC_STATUS_BUFF_EMPTY;
+ break;
+
+ case GPMC_GET_SET_IRQ_STATUS:
+ if (write)
+ gpmc_write_reg(GPMC_IRQSTATUS, wval);
+ else
+ *rval = gpmc_read_reg(GPMC_IRQSTATUS);
+ break;
+
+ case GPMC_PREFETCH_FIFO_CNT:
+ regval = gpmc_read_reg(GPMC_PREFETCH_STATUS);
+ *rval = GPMC_PREFETCH_STATUS_FIFO_CNT(regval);
+ break;
+
+ case GPMC_PREFETCH_COUNT:
+ regval = gpmc_read_reg(GPMC_PREFETCH_STATUS);
+ *rval = GPMC_PREFETCH_STATUS_COUNT(regval);
+ break;
+
+ case GPMC_CONFIG_WP:
+ regval = gpmc_read_reg(GPMC_CONFIG);
+ if (wval)
+ regval &= ~GPMC_CONFIG_WRITEPROTECT; /* WP is ON */
+ else
+ regval |= GPMC_CONFIG_WRITEPROTECT; /* WP is OFF */
+ gpmc_write_reg(GPMC_CONFIG, regval);
+ break;
+
+ case GPMC_CONFIG_RDY_BSY:
+ regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
+ regval |= WR_RD_PIN_MONITORING;
+ gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
+ break;
+
+ case GPMC_CONFIG_DEV_SIZE:
+ regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
+ regval |= GPMC_CONFIG1_DEVICESIZE(wval);
+ gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
+ break;
+
+ case GPMC_CONFIG_DEV_TYPE:
+ regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
+ regval |= GPMC_CONFIG1_DEVICETYPE(wval);
+ if (wval == GPMC_DEVICETYPE_NOR)
+ regval |= GPMC_CONFIG1_MUXADDDATA;
+ gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
+ break;
+
+ case GPMC_NAND_COMMAND:
+ gpmc_cs_write_byte(cs, GPMC_CS_NAND_COMMAND, wval);
+ break;
+
+ case GPMC_NAND_ADDRESS:
+ gpmc_cs_write_byte(cs, GPMC_CS_NAND_ADDRESS, wval);
+ break;
+
+ case GPMC_NAND_DATA:
+ if (write)
+ gpmc_cs_write_byte(cs, GPMC_CS_NAND_DATA, wval);
+ else
+ *rval = gpmc_cs_read_byte(cs, GPMC_CS_NAND_DATA);
+ break;
+
+ default:
+ printk(KERN_ERR "gpmc_hwcontrol: Not supported\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(gpmc_hwcontrol);
+
+/**
* gpmc_prefetch_enable - configures and starts prefetch transfer
- * @cs: nand cs (chip select) number
+ * @cs: cs (chip select) number
* @dma_mode: dma mode enable (1) or disable (0)
* @u32_count: number of bytes to be transferred
* @is_write: prefetch read(0) or write post(1) mode
@@ -428,7 +538,6 @@ EXPORT_SYMBOL(gpmc_cs_free);
int gpmc_prefetch_enable(int cs, int dma_mode,
unsigned int u32_count, int is_write)
{
- uint32_t prefetch_config1;
if (!(gpmc_read_reg(GPMC_PREFETCH_CONTROL))) {
/* Set the amount of bytes to be prefetched */
@@ -437,17 +546,17 @@ int gpmc_prefetch_enable(int cs, int dma_mode,
/* Set dma/mpu mode, the prefetch read / post write and
* enable the engine. Set which cs is has requested for.
*/
- prefetch_config1 = ((cs << CS_NUM_SHIFT) |
+ gpmc_write_reg(GPMC_PREFETCH_CONFIG1, ((cs << CS_NUM_SHIFT) |
PREFETCH_FIFOTHRESHOLD |
ENABLE_PREFETCH |
(dma_mode << DMA_MPU_MODE) |
- (0x1 & is_write));
- gpmc_write_reg(GPMC_PREFETCH_CONFIG1, prefetch_config1);
+ (0x1 & is_write)));
+
+ /* Start the prefetch engine */
+ gpmc_write_reg(GPMC_PREFETCH_CONTROL, 0x1);
} else {
return -EBUSY;
}
- /* Start the prefetch engine */
- gpmc_write_reg(GPMC_PREFETCH_CONTROL, 0x1);
return 0;
}
@@ -456,13 +565,22 @@ EXPORT_SYMBOL(gpmc_prefetch_enable);
/**
* gpmc_prefetch_reset - disables and stops the prefetch engine
*/
-void gpmc_prefetch_reset(void)
+int gpmc_prefetch_reset(int cs)
{
+ u32 config1;
+
+ /* check if the same module/cs is trying to reset */
+ config1 = gpmc_read_reg(GPMC_PREFETCH_CONFIG1);
+ if (((config1 >> CS_NUM_SHIFT) & 0x7) != cs)
+ return -EINVAL;
+
/* Stop the PFPW engine */
gpmc_write_reg(GPMC_PREFETCH_CONTROL, 0x0);
/* Reset/disable the PFPW engine */
gpmc_write_reg(GPMC_PREFETCH_CONFIG1, 0x0);
+
+ return 0;
}
EXPORT_SYMBOL(gpmc_prefetch_reset);
@@ -615,3 +733,80 @@ void omap3_gpmc_restore_context(void)
}
}
#endif /* CONFIG_ARCH_OMAP3 */
+
+/**
+ * gpmc_enable_hwecc - enable hardware ecc functionality
+ * @cs: chip select number
+ * @mode: read/write mode
+ * @dev_width: device bus width(1 for x16, 0 for x8)
+ * @ecc_size: bytes for which ECC will be generated
+ */
+int gpmc_enable_hwecc(int cs, int mode, int dev_width, int ecc_size)
+{
+ unsigned int val;
+
+ /* check if ecc module is in used */
+ if (gpmc_ecc_used != -EINVAL)
+ return -EINVAL;
+
+ gpmc_ecc_used = cs;
+
+ /* clear ecc and enable bits */
+ val = ((0x00000001<<8) | 0x00000001);
+ gpmc_write_reg(GPMC_ECC_CONTROL, val);
+
+ /* program ecc and result sizes */
+ val = ((((ecc_size >> 1) - 1) << 22) | (0x0000000F));
+ gpmc_write_reg(GPMC_ECC_SIZE_CONFIG, val);
+
+ switch (mode) {
+ case GPMC_ECC_READ:
+ gpmc_write_reg(GPMC_ECC_CONTROL, 0x101);
+ break;
+ case GPMC_ECC_READSYN:
+ gpmc_write_reg(GPMC_ECC_CONTROL, 0x100);
+ break;
+ case GPMC_ECC_WRITE:
+ gpmc_write_reg(GPMC_ECC_CONTROL, 0x101);
+ break;
+ default:
+ printk(KERN_INFO "Error: Unrecognized Mode[%d]!\n", mode);
+ break;
+ }
+
+ /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */
+ val = (dev_width << 7) | (cs << 1) | (0x1);
+ gpmc_write_reg(GPMC_ECC_CONFIG, val);
+ return 0;
+}
+
+/**
+ * gpmc_calculate_ecc - generate non-inverted ecc bytes
+ * @cs: chip select number
+ * @dat: data pointer over which ecc is computed
+ * @ecc_code: ecc code buffer
+ *
+ * Using non-inverted ECC is considered ugly since writing a blank
+ * page (padding) will clear the ECC bytes. This is not a problem as long
+ * no one is trying to write data on the seemingly unused page. Reading
+ * an erased page will produce an ECC mismatch between generated and read
+ * ECC bytes that has to be dealt with separately.
+ */
+int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code)
+{
+ unsigned int val = 0x0;
+
+ if (gpmc_ecc_used != cs)
+ return -EINVAL;
+
+ /* read ecc result */
+ val = gpmc_read_reg(GPMC_ECC1_RESULT);
+ *ecc_code++ = val; /* P128e, ..., P1e */
+ *ecc_code++ = val >> 16; /* P128o, ..., P1o */
+ /* P2048o, P1024o, P512o, P256o, P2048e, P1024e, P512e, P256e */
+ *ecc_code++ = ((val >> 8) & 0x0f) | ((val >> 20) & 0xf0);
+
+ gpmc_ecc_used = -EINVAL;
+ return 0;
+}
+
diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h
index 145838a..8a1e9d9
--- a/arch/arm/plat-omap/include/plat/gpmc.h
+++ b/arch/arm/plat-omap/include/plat/gpmc.h
@@ -27,8 +27,24 @@
#define GPMC_CONFIG 0x50
#define GPMC_STATUS 0x54
-#define GPMC_CS0_BASE 0x60
-#define GPMC_CS_SIZE 0x30
+
+/* Control Commands */
+#define GPMC_CONFIG_WP 0x00000001
+#define GPMC_CONFIG_RDY_BSY 0x00000002
+#define GPMC_CONFIG_DEV_SIZE 0x00000003
+#define GPMC_CONFIG_DEV_TYPE 0x00000004
+#define GPMC_NAND_COMMAND 0x00000005
+#define GPMC_NAND_ADDRESS 0x00000006
+#define GPMC_NAND_DATA 0x00000007
+#define GPMC_STATUS_BUFFER 0x00000008 /* 1: buffer is available to write */
+#define GPMC_PREFETCH_FIFO_CNT 0x00000009 /* bytes available in FIFO for r/w */
+#define GPMC_PREFETCH_COUNT 0x0000000A /* remaining bytes to be read/write*/
+#define GPMC_GET_SET_IRQ_STATUS 0x0000000B
+
+/* ECC commands */
+#define GPMC_ECC_READ 0 /* Reset Hardware ECC for read */
+#define GPMC_ECC_WRITE 1 /* Reset Hardware ECC for write */
+#define GPMC_ECC_READSYN 2 /* Reset before syndrom is read back */
#define GPMC_CONFIG1_WRAPBURST_SUPP (1 << 31)
#define GPMC_CONFIG1_READMULTIPLE_SUPP (1 << 30)
@@ -56,6 +72,14 @@
#define GPMC_CONFIG1_FCLK_DIV4 (GPMC_CONFIG1_FCLK_DIV(3))
#define GPMC_CONFIG7_CSVALID (1 << 6)
+#define GPMC_DEVICETYPE_NOR 0
+#define GPMC_DEVICETYPE_NAND 2
+#define GPMC_CONFIG_WRITEPROTECT 0x00000010
+#define GPMC_STATUS_BUFF_EMPTY 0x00000001
+#define WR_RD_PIN_MONITORING 0x00600000
+#define GPMC_PREFETCH_STATUS_FIFO_CNT(val) ((val >> 24) & 0x7F)
+#define GPMC_PREFETCH_STATUS_COUNT(val) (val & 0x00003fff)
+
/*
* Note that all values in this struct are in nanoseconds, while
* the register values are in gpmc_fck cycles.
@@ -108,10 +132,13 @@ extern int gpmc_cs_set_reserved(int cs, int reserved);
extern int gpmc_cs_reserved(int cs);
extern int gpmc_prefetch_enable(int cs, int dma_mode,
unsigned int u32_count, int is_write);
-extern void gpmc_prefetch_reset(void);
+extern int gpmc_prefetch_reset(int cs);
extern int gpmc_prefetch_status(void);
extern void omap3_gpmc_save_context(void);
extern void omap3_gpmc_restore_context(void);
extern void gpmc_init(void);
+extern int gpmc_hwcontrol(int cs, int cmd, int write, int wval, int *rval);
+int gpmc_enable_hwecc(int cs, int mode, int dev_width, int ecc_size);
+int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code);
#endif
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index ee87325..ec8eb31
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -319,7 +319,7 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len)
} while (len);
/* disable and stop the PFPW engine */
- gpmc_prefetch_reset();
+ gpmc_prefetch_reset(info->gpmc_cs);
}
}
@@ -363,7 +363,7 @@ static void omap_write_buf_pref(struct mtd_info *mtd,
}
/* disable and stop the PFPW engine */
- gpmc_prefetch_reset();
+ gpmc_prefetch_reset(info->gpmc_cs);
}
}
^ permalink raw reply related [flat|nested] 102+ messages in thread
* [PATCH v5 2/3] omap3 nand: cleanup virtual address usages
2010-06-04 7:40 ` [PATCH v5 1/3] omap3 gpmc: functionality enhancement Sukumar Ghorai
@ 2010-06-04 7:40 ` Sukumar Ghorai
2010-06-04 7:40 ` [PATCH v5 3/3] omap3 nand: fix issue in board file to detect nand Sukumar Ghorai
2010-07-07 10:21 ` [PATCH v5 2/3] omap3 nand: cleanup virtual address usages Tony Lindgren
2010-07-07 10:18 ` [PATCH v5 1/3] omap3 gpmc: functionality enhancement Tony Lindgren
1 sibling, 2 replies; 102+ messages in thread
From: Sukumar Ghorai @ 2010-06-04 7:40 UTC (permalink / raw)
To: linux-omap; +Cc: linux-mtd, tony, mike, Sukumar Ghorai
This patch removes direct reference of gpmc address from generic nand platform code.
Nand platform code now uses wrapper functions which are implemented in gpmc module.
Signed-off-by: Sukumar Ghorai <s-ghorai@ti.com>
---
arch/arm/mach-omap2/gpmc-nand.c | 39 ++----
arch/arm/mach-omap2/gpmc.c | 9 --
arch/arm/plat-omap/include/plat/gpmc.h | 5 -
arch/arm/plat-omap/include/plat/nand.h | 6 +-
drivers/mtd/nand/omap2.c | 225 +++++++++-----------------------
5 files changed, 77 insertions(+), 207 deletions(-)
diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c
index e57fb29..80f5d94
--- a/arch/arm/mach-omap2/gpmc-nand.c
+++ b/arch/arm/mach-omap2/gpmc-nand.c
@@ -19,8 +19,6 @@
#include <plat/board.h>
#include <plat/gpmc.h>
-#define WR_RD_PIN_MONITORING 0x00600000
-
static struct omap_nand_platform_data *gpmc_nand_data;
static struct resource gpmc_nand_resource = {
@@ -71,10 +69,10 @@ static int omap2_nand_gpmc_retime(void)
t.wr_cycle = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->wr_cycle);
/* Configure GPMC */
- gpmc_cs_write_reg(gpmc_nand_data->cs, GPMC_CS_CONFIG1,
- GPMC_CONFIG1_DEVICESIZE(gpmc_nand_data->devsize) |
- GPMC_CONFIG1_DEVICETYPE_NAND);
-
+ gpmc_hwcontrol(gpmc_nand_data->cs,
+ GPMC_CONFIG_DEV_SIZE, 1, gpmc_nand_data->devsize, NULL);
+ gpmc_hwcontrol(gpmc_nand_data->cs,
+ GPMC_CONFIG_DEV_TYPE, 1, GPMC_DEVICETYPE_NAND, NULL);
err = gpmc_cs_set_timings(gpmc_nand_data->cs, &t);
if (err)
return err;
@@ -82,27 +80,13 @@ static int omap2_nand_gpmc_retime(void)
return 0;
}
-static int gpmc_nand_setup(void)
-{
- struct device *dev = &gpmc_nand_device.dev;
-
- /* Set timings in GPMC */
- if (omap2_nand_gpmc_retime() < 0) {
- dev_err(dev, "Unable to set gpmc timings\n");
- return -EINVAL;
- }
-
- return 0;
-}
-
int __init gpmc_nand_init(struct omap_nand_platform_data *_nand_data)
{
- unsigned int val;
int err = 0;
struct device *dev = &gpmc_nand_device.dev;
gpmc_nand_data = _nand_data;
- gpmc_nand_data->nand_setup = gpmc_nand_setup;
+ gpmc_nand_data->nand_setup = omap2_nand_gpmc_retime;
gpmc_nand_device.dev.platform_data = gpmc_nand_data;
err = gpmc_cs_request(gpmc_nand_data->cs, NAND_IO_SIZE,
@@ -112,19 +96,17 @@ int __init gpmc_nand_init(struct omap_nand_platform_data *_nand_data)
return err;
}
- err = gpmc_nand_setup();
+ /* Set timings in GPMC */
+ err = omap2_nand_gpmc_retime();
if (err < 0) {
- dev_err(dev, "NAND platform setup failed: %d\n", err);
+ dev_err(dev, "Unable to set gpmc timings: %d\n", err);
return err;
}
/* Enable RD PIN Monitoring Reg */
if (gpmc_nand_data->dev_ready) {
- val = gpmc_cs_read_reg(gpmc_nand_data->cs,
- GPMC_CS_CONFIG1);
- val |= WR_RD_PIN_MONITORING;
- gpmc_cs_write_reg(gpmc_nand_data->cs,
- GPMC_CS_CONFIG1, val);
+ gpmc_hwcontrol(gpmc_nand_data->cs,
+ GPMC_CONFIG_RDY_BSY, 1, 1, NULL);
}
err = platform_device_register(&gpmc_nand_device);
@@ -140,3 +122,4 @@ out_free_cs:
return err;
}
+
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index 48b5af0..91e1526 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -584,15 +584,6 @@ int gpmc_prefetch_reset(int cs)
}
EXPORT_SYMBOL(gpmc_prefetch_reset);
-/**
- * gpmc_prefetch_status - reads prefetch status of engine
- */
-int gpmc_prefetch_status(void)
-{
- return gpmc_read_reg(GPMC_PREFETCH_STATUS);
-}
-EXPORT_SYMBOL(gpmc_prefetch_status);
-
static void __init gpmc_mem_init(void)
{
int cs;
diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h
index 8a1e9d9..ccbc530
--- a/arch/arm/plat-omap/include/plat/gpmc.h
+++ b/arch/arm/plat-omap/include/plat/gpmc.h
@@ -25,9 +25,6 @@
#define GPMC_CS_NAND_ADDRESS 0x20
#define GPMC_CS_NAND_DATA 0x24
-#define GPMC_CONFIG 0x50
-#define GPMC_STATUS 0x54
-
/* Control Commands */
#define GPMC_CONFIG_WP 0x00000001
#define GPMC_CONFIG_RDY_BSY 0x00000002
@@ -63,7 +60,6 @@
#define GPMC_CONFIG1_DEVICESIZE_16 GPMC_CONFIG1_DEVICESIZE(1)
#define GPMC_CONFIG1_DEVICETYPE(val) ((val & 3) << 10)
#define GPMC_CONFIG1_DEVICETYPE_NOR GPMC_CONFIG1_DEVICETYPE(0)
-#define GPMC_CONFIG1_DEVICETYPE_NAND GPMC_CONFIG1_DEVICETYPE(2)
#define GPMC_CONFIG1_MUXADDDATA (1 << 9)
#define GPMC_CONFIG1_TIME_PARA_GRAN (1 << 4)
#define GPMC_CONFIG1_FCLK_DIV(val) (val & 3)
@@ -133,7 +129,6 @@ extern int gpmc_cs_reserved(int cs);
extern int gpmc_prefetch_enable(int cs, int dma_mode,
unsigned int u32_count, int is_write);
extern int gpmc_prefetch_reset(int cs);
-extern int gpmc_prefetch_status(void);
extern void omap3_gpmc_save_context(void);
extern void omap3_gpmc_restore_context(void);
extern void gpmc_init(void);
diff --git a/arch/arm/plat-omap/include/plat/nand.h b/arch/arm/plat-omap/include/plat/nand.h
index f8efd54..6562cd0
--- a/arch/arm/plat-omap/include/plat/nand.h
+++ b/arch/arm/plat-omap/include/plat/nand.h
@@ -21,13 +21,11 @@ struct omap_nand_platform_data {
int (*dev_ready)(struct omap_nand_platform_data *);
int dma_channel;
unsigned long phys_base;
- void __iomem *gpmc_cs_baseaddr;
- void __iomem *gpmc_baseaddr;
int devsize;
};
-/* size (4 KiB) for IO mapping */
-#define NAND_IO_SIZE SZ_4K
+/* minimum size for IO mapping */
+#define NAND_IO_SIZE 4
#if defined(CONFIG_MTD_NAND_OMAP2) || defined(CONFIG_MTD_NAND_OMAP2_MODULE)
extern int gpmc_nand_init(struct omap_nand_platform_data *d);
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index ec8eb31..f9fa3cb
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -7,6 +7,7 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
+#define CONFIG_MTD_NAND_OMAP_HWECC
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
@@ -23,20 +24,8 @@
#include <plat/gpmc.h>
#include <plat/nand.h>
-#define GPMC_IRQ_STATUS 0x18
-#define GPMC_ECC_CONFIG 0x1F4
-#define GPMC_ECC_CONTROL 0x1F8
-#define GPMC_ECC_SIZE_CONFIG 0x1FC
-#define GPMC_ECC1_RESULT 0x200
-
#define DRIVER_NAME "omap2-nand"
-#define NAND_WP_OFF 0
-#define NAND_WP_BIT 0x00000010
-
-#define GPMC_BUF_FULL 0x00000001
-#define GPMC_BUF_EMPTY 0x00000000
-
#define NAND_Ecc_P1e (1 << 0)
#define NAND_Ecc_P2e (1 << 1)
#define NAND_Ecc_P4e (1 << 2)
@@ -139,34 +128,11 @@ struct omap_nand_info {
int gpmc_cs;
unsigned long phys_base;
- void __iomem *gpmc_cs_baseaddr;
- void __iomem *gpmc_baseaddr;
- void __iomem *nand_pref_fifo_add;
struct completion comp;
int dma_ch;
};
/**
- * omap_nand_wp - This function enable or disable the Write Protect feature
- * @mtd: MTD device structure
- * @mode: WP ON/OFF
- */
-static void omap_nand_wp(struct mtd_info *mtd, int mode)
-{
- struct omap_nand_info *info = container_of(mtd,
- struct omap_nand_info, mtd);
-
- unsigned long config = __raw_readl(info->gpmc_baseaddr + GPMC_CONFIG);
-
- if (mode)
- config &= ~(NAND_WP_BIT); /* WP is ON */
- else
- config |= (NAND_WP_BIT); /* WP is OFF */
-
- __raw_writel(config, (info->gpmc_baseaddr + GPMC_CONFIG));
-}
-
-/**
* omap_hwcontrol - hardware specific access to control-lines
* @mtd: MTD device structure
* @cmd: command to device
@@ -181,31 +147,20 @@ static void omap_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
struct omap_nand_info *info = container_of(mtd,
struct omap_nand_info, mtd);
- switch (ctrl) {
- case NAND_CTRL_CHANGE | NAND_CTRL_CLE:
- info->nand.IO_ADDR_W = info->gpmc_cs_baseaddr +
- GPMC_CS_NAND_COMMAND;
- info->nand.IO_ADDR_R = info->gpmc_cs_baseaddr +
- GPMC_CS_NAND_DATA;
- break;
-
- case NAND_CTRL_CHANGE | NAND_CTRL_ALE:
- info->nand.IO_ADDR_W = info->gpmc_cs_baseaddr +
- GPMC_CS_NAND_ADDRESS;
- info->nand.IO_ADDR_R = info->gpmc_cs_baseaddr +
- GPMC_CS_NAND_DATA;
- break;
-
- case NAND_CTRL_CHANGE | NAND_NCE:
- info->nand.IO_ADDR_W = info->gpmc_cs_baseaddr +
- GPMC_CS_NAND_DATA;
- info->nand.IO_ADDR_R = info->gpmc_cs_baseaddr +
- GPMC_CS_NAND_DATA;
- break;
- }
- if (cmd != NAND_CMD_NONE)
- __raw_writeb(cmd, info->nand.IO_ADDR_W);
+ if (cmd != NAND_CMD_NONE) {
+ if (ctrl & NAND_CLE)
+ gpmc_hwcontrol(info->gpmc_cs,
+ GPMC_NAND_COMMAND, 1, cmd, NULL);
+
+ else if (ctrl & NAND_ALE)
+ gpmc_hwcontrol(info->gpmc_cs,
+ GPMC_NAND_ADDRESS, 1, cmd, NULL);
+
+ else /* NAND_NCE */
+ gpmc_hwcontrol(info->gpmc_cs,
+ GPMC_NAND_DATA, 1, cmd, NULL);
+ }
}
/**
@@ -232,11 +187,15 @@ static void omap_write_buf8(struct mtd_info *mtd, const u_char *buf, int len)
struct omap_nand_info *info = container_of(mtd,
struct omap_nand_info, mtd);
u_char *p = (u_char *)buf;
+ u32 status = 0;
while (len--) {
iowrite8(*p++, info->nand.IO_ADDR_W);
- while (GPMC_BUF_EMPTY == (readl(info->gpmc_baseaddr +
- GPMC_STATUS) & GPMC_BUF_FULL));
+ /* wait until buffer is available for write */
+ do {
+ gpmc_hwcontrol(info->gpmc_cs,
+ GPMC_STATUS_BUFFER, 0, 0, &status);
+ } while (!status);
}
}
@@ -264,16 +223,17 @@ static void omap_write_buf16(struct mtd_info *mtd, const u_char * buf, int len)
struct omap_nand_info *info = container_of(mtd,
struct omap_nand_info, mtd);
u16 *p = (u16 *) buf;
-
+ u32 status = 0;
/* FIXME try bursts of writesw() or DMA ... */
len >>= 1;
while (len--) {
iowrite16(*p++, info->nand.IO_ADDR_W);
-
- while (GPMC_BUF_EMPTY == (readl(info->gpmc_baseaddr +
- GPMC_STATUS) & GPMC_BUF_FULL))
- ;
+ /* wait until buffer is available for write */
+ do {
+ gpmc_hwcontrol(info->gpmc_cs,
+ GPMC_STATUS_BUFFER, 0, 0, &status);
+ } while (!status);
}
}
@@ -287,7 +247,7 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len)
{
struct omap_nand_info *info = container_of(mtd,
struct omap_nand_info, mtd);
- uint32_t pfpw_status = 0, r_count = 0;
+ uint32_t r_count = 0;
int ret = 0;
u32 *p = (u32 *)buf;
@@ -310,14 +270,15 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len)
else
omap_read_buf8(mtd, buf, len);
} else {
+ p = (u32 *) buf;
do {
- pfpw_status = gpmc_prefetch_status();
- r_count = ((pfpw_status >> 24) & 0x7F) >> 2;
- ioread32_rep(info->nand_pref_fifo_add, p, r_count);
+ gpmc_hwcontrol(info->gpmc_cs,
+ GPMC_PREFETCH_FIFO_CNT, 0, 0, &r_count);
+ r_count = r_count >> 2;
+ ioread32_rep(info->nand.IO_ADDR_R, p, r_count);
p += r_count;
len -= r_count << 2;
} while (len);
-
/* disable and stop the PFPW engine */
gpmc_prefetch_reset(info->gpmc_cs);
}
@@ -334,13 +295,13 @@ static void omap_write_buf_pref(struct mtd_info *mtd,
{
struct omap_nand_info *info = container_of(mtd,
struct omap_nand_info, mtd);
- uint32_t pfpw_status = 0, w_count = 0;
+ uint32_t pref_count = 0, w_count = 0;
int i = 0, ret = 0;
- u16 *p = (u16 *) buf;
+ u16 *p;
/* take care of subpage writes */
if (len % 2 != 0) {
- writeb(*buf, info->nand.IO_ADDR_R);
+ writeb(*buf, info->nand.IO_ADDR_W);
p = (u16 *)(buf + 1);
len--;
}
@@ -354,14 +315,19 @@ static void omap_write_buf_pref(struct mtd_info *mtd,
else
omap_write_buf8(mtd, buf, len);
} else {
- pfpw_status = gpmc_prefetch_status();
- while (pfpw_status & 0x3FFF) {
- w_count = ((pfpw_status >> 24) & 0x7F) >> 1;
+ p = (u16 *) buf;
+ while (len) {
+ gpmc_hwcontrol(info->gpmc_cs,
+ GPMC_PREFETCH_FIFO_CNT, 0, 0, &w_count);
+ w_count = w_count >> 1;
for (i = 0; (i < w_count) && len; i++, len -= 2)
- iowrite16(*p++, info->nand_pref_fifo_add);
- pfpw_status = gpmc_prefetch_status();
+ iowrite16(*p++, info->nand.IO_ADDR_W);
}
-
+ /* wait for data to flushed-out before reset the prefetch */
+ do {
+ gpmc_hwcontrol(info->gpmc_cs,
+ GPMC_PREFETCH_COUNT, 0, 0, &pref_count);
+ } while (pref_count);
/* disable and stop the PFPW engine */
gpmc_prefetch_reset(info->gpmc_cs);
}
@@ -451,8 +417,10 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr,
/* setup and start DMA using dma_addr */
wait_for_completion(&info->comp);
- while (0x3fff & (prefetch_status = gpmc_prefetch_status()))
- ;
+ do {
+ gpmc_hwcontrol(info->gpmc_cs,
+ GPMC_PREFETCH_COUNT, 0, 0, &prefetch_status);
+ } while (prefetch_status);
/* disable and stop the PFPW engine */
gpmc_prefetch_reset();
@@ -530,29 +498,6 @@ static int omap_verify_buf(struct mtd_info *mtd, const u_char * buf, int len)
}
#ifdef CONFIG_MTD_NAND_OMAP_HWECC
-/**
- * omap_hwecc_init - Initialize the HW ECC for NAND flash in GPMC controller
- * @mtd: MTD device structure
- */
-static void omap_hwecc_init(struct mtd_info *mtd)
-{
- struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
- mtd);
- struct nand_chip *chip = mtd->priv;
- unsigned long val = 0x0;
-
- /* Read from ECC Control Register */
- val = __raw_readl(info->gpmc_baseaddr + GPMC_ECC_CONTROL);
- /* Clear all ECC | Enable Reg1 */
- val = ((0x00000001<<8) | 0x00000001);
- __raw_writel(val, info->gpmc_baseaddr + GPMC_ECC_CONTROL);
-
- /* Read from ECC Size Config Register */
- val = __raw_readl(info->gpmc_baseaddr + GPMC_ECC_SIZE_CONFIG);
- /* ECCSIZE1=512 | Select eccResultsize[0-3] */
- val = ((((chip->ecc.size >> 1) - 1) << 22) | (0x0000000F));
- __raw_writel(val, info->gpmc_baseaddr + GPMC_ECC_SIZE_CONFIG);
-}
/**
* gen_true_ecc - This function will generate true ECC value
@@ -755,19 +700,7 @@ static int omap_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
{
struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
mtd);
- unsigned long val = 0x0;
- unsigned long reg;
-
- /* Start Reading from HW ECC1_Result = 0x200 */
- reg = (unsigned long)(info->gpmc_baseaddr + GPMC_ECC1_RESULT);
- val = __raw_readl(reg);
- *ecc_code++ = val; /* P128e, ..., P1e */
- *ecc_code++ = val >> 16; /* P128o, ..., P1o */
- /* P2048o, P1024o, P512o, P256o, P2048e, P1024e, P512e, P256e */
- *ecc_code++ = ((val >> 8) & 0x0f) | ((val >> 20) & 0xf0);
- reg += 4;
-
- return 0;
+ return gpmc_calculate_ecc(info->gpmc_cs, dat, ecc_code);
}
/**
@@ -781,32 +714,10 @@ static void omap_enable_hwecc(struct mtd_info *mtd, int mode)
mtd);
struct nand_chip *chip = mtd->priv;
unsigned int dev_width = (chip->options & NAND_BUSWIDTH_16) ? 1 : 0;
- unsigned long val = __raw_readl(info->gpmc_baseaddr + GPMC_ECC_CONFIG);
-
- switch (mode) {
- case NAND_ECC_READ:
- __raw_writel(0x101, info->gpmc_baseaddr + GPMC_ECC_CONTROL);
- /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */
- val = (dev_width << 7) | (info->gpmc_cs << 1) | (0x1);
- break;
- case NAND_ECC_READSYN:
- __raw_writel(0x100, info->gpmc_baseaddr + GPMC_ECC_CONTROL);
- /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */
- val = (dev_width << 7) | (info->gpmc_cs << 1) | (0x1);
- break;
- case NAND_ECC_WRITE:
- __raw_writel(0x101, info->gpmc_baseaddr + GPMC_ECC_CONTROL);
- /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */
- val = (dev_width << 7) | (info->gpmc_cs << 1) | (0x1);
- break;
- default:
- DEBUG(MTD_DEBUG_LEVEL0, "Error: Unrecognized Mode[%d]!\n",
- mode);
- break;
- }
- __raw_writel(val, info->gpmc_baseaddr + GPMC_ECC_CONFIG);
+ gpmc_enable_hwecc(info->gpmc_cs, mode, dev_width, info->nand.ecc.size);
}
+
#endif
/**
@@ -834,14 +745,10 @@ static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip)
else
timeo += (HZ * 20) / 1000;
- this->IO_ADDR_W = (void *) info->gpmc_cs_baseaddr +
- GPMC_CS_NAND_COMMAND;
- this->IO_ADDR_R = (void *) info->gpmc_cs_baseaddr + GPMC_CS_NAND_DATA;
-
- __raw_writeb(NAND_CMD_STATUS & 0xFF, this->IO_ADDR_W);
-
+ gpmc_hwcontrol(info->gpmc_cs,
+ GPMC_NAND_COMMAND, 1, (NAND_CMD_STATUS & 0xFF), NULL);
while (time_before(jiffies, timeo)) {
- status = __raw_readb(this->IO_ADDR_R);
+ gpmc_hwcontrol(info->gpmc_cs, GPMC_NAND_DATA, 0, 0, &status);
if (status & NAND_STATUS_READY)
break;
cond_resched();
@@ -855,22 +762,24 @@ static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip)
*/
static int omap_dev_ready(struct mtd_info *mtd)
{
+ unsigned int val = 0;
struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
mtd);
- unsigned int val = __raw_readl(info->gpmc_baseaddr + GPMC_IRQ_STATUS);
+ gpmc_hwcontrol(info->gpmc_cs, GPMC_GET_SET_IRQ_STATUS, 0, 0, &val);
if ((val & 0x100) == 0x100) {
/* Clear IRQ Interrupt */
val |= 0x100;
val &= ~(0x0);
- __raw_writel(val, info->gpmc_baseaddr + GPMC_IRQ_STATUS);
+ gpmc_hwcontrol(info->gpmc_cs,
+ GPMC_GET_SET_IRQ_STATUS, 1, val, NULL);
} else {
unsigned int cnt = 0;
while (cnt++ < 0x1FF) {
if ((val & 0x100) == 0x100)
return 0;
- val = __raw_readl(info->gpmc_baseaddr +
- GPMC_IRQ_STATUS);
+ gpmc_hwcontrol(info->gpmc_cs,
+ GPMC_GET_SET_IRQ_STATUS, 0, 0, &val);
}
}
@@ -901,8 +810,6 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
info->pdev = pdev;
info->gpmc_cs = pdata->cs;
- info->gpmc_baseaddr = pdata->gpmc_baseaddr;
- info->gpmc_cs_baseaddr = pdata->gpmc_cs_baseaddr;
info->phys_base = pdata->phys_base;
info->mtd.priv = &info->nand;
@@ -913,7 +820,7 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
info->nand.options |= NAND_SKIP_BBTSCAN;
/* NAND write protect off */
- omap_nand_wp(&info->mtd, NAND_WP_OFF);
+ gpmc_hwcontrol(info->gpmc_cs, GPMC_CONFIG_WP, 1, 0, NULL);
if (!request_mem_region(info->phys_base, NAND_IO_SIZE,
pdev->dev.driver->name)) {
@@ -948,8 +855,6 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
}
if (use_prefetch) {
- /* copy the virtual address of nand base for fifo access */
- info->nand_pref_fifo_add = info->nand.IO_ADDR_R;
info->nand.read_buf = omap_read_buf_pref;
info->nand.write_buf = omap_write_buf_pref;
@@ -989,8 +894,6 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
info->nand.ecc.correct = omap_correct_data;
info->nand.ecc.mode = NAND_ECC_HW;
- /* init HW ECC */
- omap_hwecc_init(&info->mtd);
#else
info->nand.ecc.mode = NAND_ECC_SOFT;
#endif
@@ -1040,7 +943,7 @@ static int omap_nand_remove(struct platform_device *pdev)
/* Release NAND device, its internal structures and partitions */
nand_release(&info->mtd);
- iounmap(info->nand_pref_fifo_add);
+ iounmap(info->nand.IO_ADDR_R);
kfree(&info->mtd);
return 0;
}
^ permalink raw reply related [flat|nested] 102+ messages in thread
* [PATCH v5 3/3] omap3 nand: fix issue in board file to detect nand
2010-06-04 7:40 ` [PATCH v5 2/3] omap3 nand: cleanup virtual address usages Sukumar Ghorai
@ 2010-06-04 7:40 ` Sukumar Ghorai
2010-07-07 10:21 ` [PATCH v5 2/3] omap3 nand: cleanup virtual address usages Tony Lindgren
1 sibling, 0 replies; 102+ messages in thread
From: Sukumar Ghorai @ 2010-06-04 7:40 UTC (permalink / raw)
To: linux-omap; +Cc: linux-mtd, tony, mike, Sukumar Ghorai
Board file modified for not to provide gpmc phys_base address to nand driver.
The gpmc_nand_init funciton is now used to detect the nand and required to
adopt _prob function as in nand/omap2.c
Signed-off-by: Sukumar Ghorai <s-ghorai@ti.com>
---
arch/arm/mach-omap2/board-cm-t35.c | 20 +-------------------
arch/arm/mach-omap2/board-devkit8000.c | 25 +------------------------
arch/arm/mach-omap2/board-omap3beagle.c | 24 +-----------------------
arch/arm/mach-omap2/board-omap3touchbook.c | 25 +------------------------
arch/arm/mach-omap2/board-overo.c | 24 +-----------------------
arch/arm/mach-omap2/board-sdp-flash.c | 5 -----
6 files changed, 5 insertions(+), 118 deletions(-)
diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c
index bc4c3f8..4870da2
--- a/arch/arm/mach-omap2/board-cm-t35.c
+++ b/arch/arm/mach-omap2/board-cm-t35.c
@@ -61,8 +61,6 @@
#define SB_T35_SMSC911X_GPIO 65
#define NAND_BLOCK_SIZE SZ_128K
-#define GPMC_CS0_BASE 0x60
-#define GPMC_CS0_BASE_ADDR (OMAP34XX_GPMC_VIRT + GPMC_CS0_BASE)
#if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
#include <linux/smsc911x.h>
@@ -223,28 +221,12 @@ static struct omap_nand_platform_data cm_t35_nand_data = {
.nr_parts = ARRAY_SIZE(cm_t35_nand_partitions),
.dma_channel = -1, /* disable DMA in OMAP NAND driver */
.cs = 0,
- .gpmc_cs_baseaddr = (void __iomem *)GPMC_CS0_BASE_ADDR,
- .gpmc_baseaddr = (void __iomem *)OMAP34XX_GPMC_VIRT,
};
-static struct resource cm_t35_nand_resource = {
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device cm_t35_nand_device = {
- .name = "omap2-nand",
- .id = -1,
- .num_resources = 1,
- .resource = &cm_t35_nand_resource,
- .dev = {
- .platform_data = &cm_t35_nand_data,
- },
-};
-
static void __init cm_t35_init_nand(void)
{
- if (platform_device_register(&cm_t35_nand_device) < 0)
+ if (gpmc_nand_init(&cm_t35_nand_data) < 0)
pr_err("CM-T35: Unable to register NAND device\n");
}
#else
diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c
index 922b746..364511a
--- a/arch/arm/mach-omap2/board-devkit8000.c
+++ b/arch/arm/mach-omap2/board-devkit8000.c
@@ -58,9 +58,6 @@
#include "mux.h"
#include "hsmmc.h"
-#define GPMC_CS0_BASE 0x60
-#define GPMC_CS_SIZE 0x30
-
#define NAND_BLOCK_SIZE SZ_128K
#define OMAP_DM9000_GPIO_IRQ 25
@@ -104,20 +101,6 @@ static struct omap_nand_platform_data devkit8000_nand_data = {
.dma_channel = -1, /* disable DMA in OMAP NAND driver */
};
-static struct resource devkit8000_nand_resource = {
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device devkit8000_nand_device = {
- .name = "omap2-nand",
- .id = -1,
- .dev = {
- .platform_data = &devkit8000_nand_data,
- },
- .num_resources = 1,
- .resource = &devkit8000_nand_resource,
-};
-
static struct omap2_hsmmc_info mmc[] = {
{
.mmc = 1,
@@ -581,8 +564,6 @@ static void __init devkit8000_flash_init(void)
u8 cs = 0;
u8 nandcs = GPMC_CS_NUM + 1;
- u32 gpmc_base_add = OMAP34XX_GPMC_VIRT;
-
/* find out the chip-select on which NAND exists */
while (cs < GPMC_CS_NUM) {
u32 ret = 0;
@@ -604,13 +585,9 @@ static void __init devkit8000_flash_init(void)
if (nandcs < GPMC_CS_NUM) {
devkit8000_nand_data.cs = nandcs;
- devkit8000_nand_data.gpmc_cs_baseaddr = (void *)
- (gpmc_base_add + GPMC_CS0_BASE + nandcs * GPMC_CS_SIZE);
- devkit8000_nand_data.gpmc_baseaddr = (void *)
- (gpmc_base_add);
printk(KERN_INFO "Registering NAND on CS%d\n", nandcs);
- if (platform_device_register(&devkit8000_nand_device) < 0)
+ if (gpmc_nand_init(&devkit8000_nand_data) < 0)
printk(KERN_ERR "Unable to register NAND device\n");
}
}
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index 0ab0c26..befb5e3
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -48,9 +48,6 @@
#include "mux.h"
#include "hsmmc.h"
-#define GPMC_CS0_BASE 0x60
-#define GPMC_CS_SIZE 0x30
-
#define NAND_BLOCK_SIZE SZ_128K
static struct mtd_partition omap3beagle_nand_partitions[] = {
@@ -93,20 +90,6 @@ static struct omap_nand_platform_data omap3beagle_nand_data = {
.dev_ready = NULL,
};
-static struct resource omap3beagle_nand_resource = {
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device omap3beagle_nand_device = {
- .name = "omap2-nand",
- .id = -1,
- .dev = {
- .platform_data = &omap3beagle_nand_data,
- },
- .num_resources = 1,
- .resource = &omap3beagle_nand_resource,
-};
-
/* DSS */
static int beagle_enable_dvi(struct omap_dss_device *dssdev)
@@ -424,8 +407,6 @@ static void __init omap3beagle_flash_init(void)
u8 cs = 0;
u8 nandcs = GPMC_CS_NUM + 1;
- u32 gpmc_base_add = OMAP34XX_GPMC_VIRT;
-
/* find out the chip-select on which NAND exists */
while (cs < GPMC_CS_NUM) {
u32 ret = 0;
@@ -447,12 +428,9 @@ static void __init omap3beagle_flash_init(void)
if (nandcs < GPMC_CS_NUM) {
omap3beagle_nand_data.cs = nandcs;
- omap3beagle_nand_data.gpmc_cs_baseaddr = (void *)
- (gpmc_base_add + GPMC_CS0_BASE + nandcs * GPMC_CS_SIZE);
- omap3beagle_nand_data.gpmc_baseaddr = (void *) (gpmc_base_add);
printk(KERN_INFO "Registering NAND on CS%d\n", nandcs);
- if (platform_device_register(&omap3beagle_nand_device) < 0)
+ if (gpmc_nand_init(&omap3beagle_nand_data) < 0)
printk(KERN_ERR "Unable to register NAND device\n");
}
}
diff --git a/arch/arm/mach-omap2/board-omap3touchbook.c b/arch/arm/mach-omap2/board-omap3touchbook.c
index f05b867..bf8089f
--- a/arch/arm/mach-omap2/board-omap3touchbook.c
+++ b/arch/arm/mach-omap2/board-omap3touchbook.c
@@ -54,9 +54,6 @@
#include <asm/setup.h>
-#define GPMC_CS0_BASE 0x60
-#define GPMC_CS_SIZE 0x30
-
#define NAND_BLOCK_SIZE SZ_128K
#define OMAP3_AC_GPIO 136
@@ -106,20 +103,6 @@ static struct omap_nand_platform_data omap3touchbook_nand_data = {
.dev_ready = NULL,
};
-static struct resource omap3touchbook_nand_resource = {
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device omap3touchbook_nand_device = {
- .name = "omap2-nand",
- .id = -1,
- .dev = {
- .platform_data = &omap3touchbook_nand_data,
- },
- .num_resources = 1,
- .resource = &omap3touchbook_nand_resource,
-};
-
#include "sdram-micron-mt46h32m32lf-6.h"
static struct omap2_hsmmc_info mmc[] = {
@@ -458,8 +441,6 @@ static void __init omap3touchbook_flash_init(void)
u8 cs = 0;
u8 nandcs = GPMC_CS_NUM + 1;
- u32 gpmc_base_add = OMAP34XX_GPMC_VIRT;
-
/* find out the chip-select on which NAND exists */
while (cs < GPMC_CS_NUM) {
u32 ret = 0;
@@ -481,13 +462,9 @@ static void __init omap3touchbook_flash_init(void)
if (nandcs < GPMC_CS_NUM) {
omap3touchbook_nand_data.cs = nandcs;
- omap3touchbook_nand_data.gpmc_cs_baseaddr = (void *)
- (gpmc_base_add + GPMC_CS0_BASE + nandcs * GPMC_CS_SIZE);
- omap3touchbook_nand_data.gpmc_baseaddr =
- (void *) (gpmc_base_add);
printk(KERN_INFO "Registering NAND on CS%d\n", nandcs);
- if (platform_device_register(&omap3touchbook_nand_device) < 0)
+ if (gpmc_nand_init(&omap3touchbook_nand_data) < 0)
printk(KERN_ERR "Unable to register NAND device\n");
}
}
diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
index d05ced5..9c51936
--- a/arch/arm/mach-omap2/board-overo.c
+++ b/arch/arm/mach-omap2/board-overo.c
@@ -58,8 +58,6 @@
#define OVERO_GPIO_USBH_NRESET 183
#define NAND_BLOCK_SIZE SZ_128K
-#define GPMC_CS0_BASE 0x60
-#define GPMC_CS_SIZE 0x30
#define OVERO_SMSC911X_CS 5
#define OVERO_SMSC911X_GPIO 176
@@ -269,28 +267,11 @@ static struct omap_nand_platform_data overo_nand_data = {
.dma_channel = -1, /* disable DMA in OMAP NAND driver */
};
-static struct resource overo_nand_resource = {
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device overo_nand_device = {
- .name = "omap2-nand",
- .id = -1,
- .dev = {
- .platform_data = &overo_nand_data,
- },
- .num_resources = 1,
- .resource = &overo_nand_resource,
-};
-
-
static void __init overo_flash_init(void)
{
u8 cs = 0;
u8 nandcs = GPMC_CS_NUM + 1;
- u32 gpmc_base_add = OMAP34XX_GPMC_VIRT;
-
/* find out the chip-select on which NAND exists */
while (cs < GPMC_CS_NUM) {
u32 ret = 0;
@@ -312,12 +293,9 @@ static void __init overo_flash_init(void)
if (nandcs < GPMC_CS_NUM) {
overo_nand_data.cs = nandcs;
- overo_nand_data.gpmc_cs_baseaddr = (void *)
- (gpmc_base_add + GPMC_CS0_BASE + nandcs * GPMC_CS_SIZE);
- overo_nand_data.gpmc_baseaddr = (void *) (gpmc_base_add);
printk(KERN_INFO "Registering NAND on CS%d\n", nandcs);
- if (platform_device_register(&overo_nand_device) < 0)
+ if (gpmc_nand_init(&overo_nand_data) < 0)
printk(KERN_ERR "Unable to register NAND device\n");
}
}
diff --git a/arch/arm/mach-omap2/board-sdp-flash.c b/arch/arm/mach-omap2/board-sdp-flash.c
old mode 100644
new mode 100755
index 2d02632..2638c83
--- a/arch/arm/mach-omap2/board-sdp-flash.c
+++ b/arch/arm/mach-omap2/board-sdp-flash.c
@@ -162,11 +162,6 @@ __init board_nand_init(struct flash_partitions sdp_nand_parts, u8 cs)
sdp_nand_data.parts = sdp_nand_parts.parts;
sdp_nand_data.nr_parts = sdp_nand_parts.nr_parts;
- sdp_nand_data.gpmc_cs_baseaddr = (void *)(OMAP34XX_GPMC_VIRT +
- GPMC_CS0_BASE +
- cs * GPMC_CS_SIZE);
- sdp_nand_data.gpmc_baseaddr = (void *) (OMAP34XX_GPMC_VIRT);
-
gpmc_nand_init(&sdp_nand_data);
}
#else
^ permalink raw reply related [flat|nested] 102+ messages in thread
* Re: [PATCH v5 0/3] omap3 nand: cleanup exiting platform related code
2010-06-04 7:40 ` [PATCH v5 0/3] omap3 nand: cleanup exiting platform related code Sukumar Ghorai
2010-06-04 7:40 ` [PATCH v5 1/3] omap3 gpmc: functionality enhancement Sukumar Ghorai
@ 2010-06-08 17:12 ` Vimal Singh
2010-06-15 13:26 ` Ghorai, Sukumar
2010-06-30 14:42 ` Ghorai, Sukumar
1 sibling, 2 replies; 102+ messages in thread
From: Vimal Singh @ 2010-06-08 17:12 UTC (permalink / raw)
To: Sukumar Ghorai; +Cc: linux-omap, linux-mtd, tony, mike
Reviewed-by: Vimal Singh <vimal.newwork@gmail.com>
On Fri, Jun 4, 2010 at 1:10 PM, Sukumar Ghorai <s-ghorai@ti.com> wrote:
> The following set of patches applies on top of for-next branch.
> http://git.kernel.org/?p=linux/kernel/git/tmlind/linux-omap-2.6.git
> Patches verified on: omap3430-SDP, omap3630-sdp, zoom3 and beagle board
>
> And these are the patches required to address the following input -
> 1. The NAND driver needs to stop tinkering with the GPMC registers
> The omap General Purpose Memory Controller (GPMC) registers are omap
> specific, and not driver specific. Tinkering with these registers can
> cause issues with the other devices on the GPMC.
>
> 2. Passing hardcoded GPMC_CS0_BASE needs to go from the board files
> Passing hardcoded GPMC virtual addressess is sure way to mess up things.
> This should all become unnecessary once the NAND drivers stops messing
> with the GPMC registers directly.
> Discussion: http://www.mail-archive.com/linux-omap@vger.kernel.org/msg27630.html
>
> Changes in this series -
> Unused function removed.
>
> Functions related to ecc and prefetch engine are optimized.
> v4: http://www.mail-archive.com/linux-omap@vger.kernel.org/msg29458.html
>
> Few functionality was missing like - There should be some locking as only
> one chipselect can use the ECC or prefetch engine at a time. If you have
> NAND in two chipselects, bad things would happen.
> v3: http://www.mail-archive.com/linux-omap@vger.kernel.org/msg28715.html
>
> Additionally, it was needed to implement more functions for the platform
> init code to use.
> v2: http://www.mail-archive.com/linux-omap@vger.kernel.org/msg28467.html
>
> v1: http://www.mail-archive.com/linux-omap@vger.kernel.org/msg28164.html
>
>
> Sukumar Ghorai (3):
> omap3 gpmc: functionality enhancement
> omap3 nand: cleanup virtual address usages
> omap3 nand: fix issue in board file to detect nand
> arch/arm/mach-omap2/board-cm-t35.c | 20 +---
> arch/arm/mach-omap2/board-devkit8000.c | 25 +---
> arch/arm/mach-omap2/board-omap3beagle.c | 24 +---
> arch/arm/mach-omap2/board-omap3touchbook.c | 25 +---
> arch/arm/mach-omap2/board-overo.c | 24 +---
> arch/arm/mach-omap2/board-sdp-flash.c | 5 -
> arch/arm/mach-omap2/gpmc-nand.c | 39 ++----
> arch/arm/mach-omap2/gpmc.c | 228 +++++++++++++++++++++++++---
> arch/arm/plat-omap/include/plat/gpmc.h | 36 ++++-
> arch/arm/plat-omap/include/plat/nand.h | 6 +-
> drivers/mtd/nand/omap2.c | 229 ++++++++--------------------
> 11 files changed, 320 insertions(+), 341 deletions(-)
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
--
Regards,
Vimal Singh
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 102+ messages in thread
* RE: [PATCH v5 0/3] omap3 nand: cleanup exiting platform related code
2010-06-08 17:12 ` [PATCH v5 0/3] omap3 nand: cleanup exiting platform related code Vimal Singh
@ 2010-06-15 13:26 ` Ghorai, Sukumar
2010-06-30 14:42 ` Ghorai, Sukumar
1 sibling, 0 replies; 102+ messages in thread
From: Ghorai, Sukumar @ 2010-06-15 13:26 UTC (permalink / raw)
Cc: linux-omap@vger.kernel.org, linux-mtd@lists.infradead.org,
tony@atomide.com, mike@compulab.co.il, Vimal Singh
Tony,
> -----Original Message-----
> From: Vimal Singh [mailto:vimal.newwork@gmail.com]
> Sent: Tuesday, June 08, 2010 10:43 PM
> To: Ghorai, Sukumar
> Cc: linux-omap@vger.kernel.org; linux-mtd@lists.infradead.org;
> tony@atomide.com; mike@compulab.co.il
> Subject: Re: [PATCH v5 0/3] omap3 nand: cleanup exiting platform related
> code
>
> Reviewed-by: Vimal Singh <vimal.newwork@gmail.com>
>
> On Fri, Jun 4, 2010 at 1:10 PM, Sukumar Ghorai <s-ghorai@ti.com> wrote:
> > The following set of patches applies on top of for-next branch.
> > http://git.kernel.org/?p=linux/kernel/git/tmlind/linux-omap-
> 2.6.git
> > Patches verified on: omap3430-SDP, omap3630-sdp, zoom3 and beagle
> board
> >
> > And these are the patches required to address the following input -
> > 1. The NAND driver needs to stop tinkering with the GPMC registers
> > The omap General Purpose Memory Controller (GPMC) registers are
> omap
> > specific, and not driver specific. Tinkering with these registers
> can
> > cause issues with the other devices on the GPMC.
> >
> > 2. Passing hardcoded GPMC_CS0_BASE needs to go from the board files
> > Passing hardcoded GPMC virtual addressess is sure way to mess up
> things.
> > This should all become unnecessary once the NAND drivers stops
> messing
> > with the GPMC registers directly.
> > Discussion: http://www.mail-archive.com/linux-
> omap@vger.kernel.org/msg27630.html
> >
> > Changes in this series -
> > Unused function removed.
> >
> > Functions related to ecc and prefetch engine are optimized.
> > v4: http://www.mail-archive.com/linux-
> omap@vger.kernel.org/msg29458.html
> >
> > Few functionality was missing like - There should be some locking as
> only
> > one chipselect can use the ECC or prefetch engine at a time. If you
> have
> > NAND in two chipselects, bad things would happen.
> > v3: http://www.mail-archive.com/linux-
> omap@vger.kernel.org/msg28715.html
> >
> > Additionally, it was needed to implement more functions for the
> platform
> > init code to use.
> > v2: http://www.mail-archive.com/linux-
> omap@vger.kernel.org/msg28467.html
> >
> > v1: http://www.mail-archive.com/linux-
> omap@vger.kernel.org/msg28164.html
> >
> >
> > Sukumar Ghorai (3):
> > omap3 gpmc: functionality enhancement
> > omap3 nand: cleanup virtual address usages
> > omap3 nand: fix issue in board file to detect nand
> > arch/arm/mach-omap2/board-cm-t35.c | 20 +---
> > arch/arm/mach-omap2/board-devkit8000.c | 25 +---
> > arch/arm/mach-omap2/board-omap3beagle.c | 24 +---
> > arch/arm/mach-omap2/board-omap3touchbook.c | 25 +---
> > arch/arm/mach-omap2/board-overo.c | 24 +---
> > arch/arm/mach-omap2/board-sdp-flash.c | 5 -
> > arch/arm/mach-omap2/gpmc-nand.c | 39 ++----
> > arch/arm/mach-omap2/gpmc.c | 228
> +++++++++++++++++++++++++---
> > arch/arm/plat-omap/include/plat/gpmc.h | 36 ++++-
> > arch/arm/plat-omap/include/plat/nand.h | 6 +-
> > drivers/mtd/nand/omap2.c | 229 ++++++++-------------
> -------
> > 11 files changed, 320 insertions(+), 341 deletions(-)
[Ghorai] Any comments or input on these patch?
> >
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at http://vger.kernel.org/majordomo-info.html
> >
>
>
>
> --
> Regards,
> Vimal Singh
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 102+ messages in thread
* [PATCH v3 0/8] nand support on omap3 boards
[not found] <Sukumar Ghorai <s-ghorai@ti.com>
` (14 preceding siblings ...)
2010-06-04 7:40 ` [PATCH v5 0/3] omap3 nand: cleanup exiting platform related code Sukumar Ghorai
@ 2010-06-16 11:39 ` Sukumar Ghorai
2010-06-16 11:39 ` [PATCH v3 1/8] omap3 flash: rename board-sdp-flash.c to be use by other boards Sukumar Ghorai
15 siblings, 1 reply; 102+ messages in thread
From: Sukumar Ghorai @ 2010-06-16 11:39 UTC (permalink / raw)
To: linux-omap; +Cc: Sukumar Ghorai
The following set of patches applies on top of for-next branch.
And these are the patches required to enable nand (nor and onenand for sdp
only) for different platform.
v3: patch rebase on latest nand patch and depend on -
http://www.mail-archive.com/linux-omap@vger.kernel.org/msg30305.html
v2: http://www.mail-archive.com/linux-omap@vger.kernel.org/msg26479.html
rework to use full nand in partition table of ZOOM2/3;
ZOOM1(LDP)support added.
v1: http://www.mail-archive.com/linux-omap@vger.kernel.org/msg22205.html
Sukumar Ghorai (8):
omap3 flash: rename board-sdp-flash.c to be use by other boards
omap3: add support for NAND on zoom2 board
omap3: add support for NAND on zoom3 board
omap-3630-sdp : Add support for Flash
omap-3630-sdp: enable Flash device support
omap3: add support for NAND on LDP board
zoom2: enable NAND support
zoom3: enable NAND support
arch/arm/configs/omap_3630sdp_defconfig | 31 +++-
arch/arm/configs/omap_zoom2_defconfig | 24 +++-
arch/arm/configs/omap_zoom3_defconfig | 24 +++-
arch/arm/mach-omap2/Makefile | 6 +-
arch/arm/mach-omap2/board-3430sdp.c | 16 ++-
arch/arm/mach-omap2/board-3630sdp.c | 120 ++++++++++++
arch/arm/mach-omap2/board-ldp.c | 35 ++++
arch/arm/mach-omap2/board-flash.c | 253 ++++++++++++++++++++++
arch/arm/mach-omap2/board-sdp-flash.c | 267 --------------------------
arch/arm/mach-omap2/board-zoom2.c | 49 +++++
arch/arm/mach-omap2/board-zoom3.c | 48 +++++
arch/arm/mach-omap2/include/mach/board-flash.h | 28 +++
arch/arm/mach-omap2/include/mach/board-sdp.h | 21 --
11 files changed, 628 insertions(+), 294 deletions(-)
^ permalink raw reply [flat|nested] 102+ messages in thread
* [PATCH v3 1/8] omap3 flash: rename board-sdp-flash.c to be use by other boards
2010-06-16 11:39 ` [PATCH v3 0/8] nand support on omap3 boards Sukumar Ghorai
@ 2010-06-16 11:39 ` Sukumar Ghorai
2010-06-16 11:39 ` [PATCH v3 2/8] omap3: add support for NAND on zoom2 board Sukumar Ghorai
2010-07-05 12:23 ` [PATCH v3 1/8] omap3 flash: rename board-sdp-flash.c to be use by other boards Tony Lindgren
0 siblings, 2 replies; 102+ messages in thread
From: Sukumar Ghorai @ 2010-06-16 11:39 UTC (permalink / raw)
To: linux-omap; +Cc: Sukumar Ghorai
rename board-sdp-flash.c(board-flash.c) and board-sdp.h(board-flash.h) to
used by other board e.g. zoom
Signed-off-by: Sukumar Ghorai <s-ghorai@ti.com>
---
arch/arm/mach-omap2/Makefile | 2 +-
arch/arm/mach-omap2/board-3430sdp.c | 16 ++-
arch/arm/mach-omap2/board-flash.c | 253 ++++++++++++++++++++++
arch/arm/mach-omap2/board-sdp-flash.c | 267 ------------------------
arch/arm/mach-omap2/include/mach/board-flash.h | 28 +++
arch/arm/mach-omap2/include/mach/board-sdp.h | 21 --
6 files changed, 296 insertions(+), 291 deletions(-)
create mode 100755 arch/arm/mach-omap2/board-flash.c
delete mode 100755 arch/arm/mach-omap2/board-sdp-flash.c
create mode 100644 arch/arm/mach-omap2/include/mach/board-flash.h
delete mode 100644 arch/arm/mach-omap2/include/mach/board-sdp.h
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index 6c6d7c6..0d854f1 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -117,7 +117,7 @@ obj-$(CONFIG_MACH_OMAP3_PANDORA) += board-omap3pandora.o \
hsmmc.o
obj-$(CONFIG_MACH_OMAP_3430SDP) += board-3430sdp.o \
hsmmc.o \
- board-sdp-flash.o
+ board-flash.o
obj-$(CONFIG_MACH_NOKIA_N8X0) += board-n8x0.o
obj-$(CONFIG_MACH_NOKIA_RX51) += board-rx51.o \
board-rx51-sdram.o \
diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
index f474a80..4b8595b 100644
--- a/arch/arm/mach-omap2/board-3430sdp.c
+++ b/arch/arm/mach-omap2/board-3430sdp.c
@@ -41,7 +41,7 @@
#include <plat/control.h>
#include <plat/gpmc-smc91x.h>
-#include <mach/board-sdp.h>
+#include <mach/board-flash.h>
#include "mux.h"
#include "sdram-qimonda-hyb18m512160af-6.h"
@@ -667,6 +667,18 @@ static struct omap_board_mux board_mux[] __initdata = {
#define board_mux NULL
#endif
+/*
+ * SDP3430 V2 Board CS organization
+ * Different from SDP3430 V1. Now 4 switches used to specify CS
+ *
+ * See also the Switch S8 settings in the comments.
+ */
+static char chip_sel_3430[][GPMC_CS_NUM] = {
+ {PDC_NOR, PDC_NAND, PDC_ONENAND, DBG_MPDB, 0, 0, 0, 0}, /* S8:1111 */
+ {PDC_ONENAND, PDC_NAND, PDC_NOR, DBG_MPDB, 0, 0, 0, 0}, /* S8:1110 */
+ {PDC_NAND, PDC_ONENAND, PDC_NOR, DBG_MPDB, 0, 0, 0, 0}, /* S8:1101 */
+};
+
static struct mtd_partition sdp_nor_partitions[] = {
/* bootloader (U-Boot, etc) in first sector */
{
@@ -797,7 +809,7 @@ static void __init omap_3430sdp_init(void)
omap_serial_init();
usb_musb_init(&musb_board_data);
board_smc91x_init();
- sdp_flash_init(sdp_flash_partitions);
+ board_flash_init(sdp_flash_partitions, chip_sel_3430);
sdp3430_display_init();
enable_board_wakeup_source();
usb_ehci_init(&ehci_pdata);
diff --git a/arch/arm/mach-omap2/board-flash.c b/arch/arm/mach-omap2/board-flash.c
new file mode 100755
index 0000000..ac834aa
--- /dev/null
+++ b/arch/arm/mach-omap2/board-flash.c
@@ -0,0 +1,253 @@
+/*
+ * board-sdp-flash.c
+ * Modified from mach-omap2/board-3430sdp-flash.c
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ * Copyright (C) 2009 Texas Instruments
+ *
+ * Vimal Singh <vimalsingh@ti.com>
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/physmap.h>
+#include <linux/io.h>
+
+#include <plat/gpmc.h>
+#include <plat/nand.h>
+#include <plat/onenand.h>
+#include <plat/tc.h>
+#include <mach/board-flash.h>
+
+#define REG_FPGA_REV 0x10
+#define REG_FPGA_DIP_SWITCH_INPUT2 0x60
+#define MAX_SUPPORTED_GPMC_CONFIG 3
+
+#define DEBUG_BASE 0x08000000 /* debug board */
+
+/* various memory sizes */
+#define FLASH_SIZE_SDPV1 SZ_64M /* NOR flash (64 Meg aligned) */
+#define FLASH_SIZE_SDPV2 SZ_128M /* NOR flash (256 Meg aligned) */
+
+static struct physmap_flash_data board_nor_data = {
+ .width = 2,
+};
+
+static struct resource board_nor_resource = {
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device board_nor_device = {
+ .name = "physmap-flash",
+ .id = 0,
+ .dev = {
+ .platform_data = &board_nor_data,
+ },
+ .num_resources = 1,
+ .resource = &board_nor_resource,
+};
+
+static void
+__init board_nor_init(struct mtd_partition *nor_parts, u8 nr_parts, u8 cs)
+{
+ int err;
+
+ board_nor_data.parts = nor_parts;
+ board_nor_data.nr_parts = nr_parts;
+
+ /* Configure start address and size of NOR device */
+ if (omap_rev() >= OMAP3430_REV_ES1_0) {
+ err = gpmc_cs_request(cs, FLASH_SIZE_SDPV2 - 1,
+ (unsigned long *)&board_nor_resource.start);
+ board_nor_resource.end = board_nor_resource.start
+ + FLASH_SIZE_SDPV2 - 1;
+ } else {
+ err = gpmc_cs_request(cs, FLASH_SIZE_SDPV1 - 1,
+ (unsigned long *)&board_nor_resource.start);
+ board_nor_resource.end = board_nor_resource.start
+ + FLASH_SIZE_SDPV1 - 1;
+ }
+ if (err < 0) {
+ printk(KERN_ERR "NOR: Can't request GPMC CS\n");
+ return;
+ }
+ if (platform_device_register(&board_nor_device) < 0)
+ printk(KERN_ERR "Unable to register NOR device\n");
+}
+
+#if defined(CONFIG_MTD_ONENAND_OMAP2) || \
+ defined(CONFIG_MTD_ONENAND_OMAP2_MODULE)
+static struct omap_onenand_platform_data board_onenand_data = {
+ .dma_channel = -1, /* disable DMA in OMAP OneNAND driver */
+};
+
+static void
+__init board_onenand_init(struct mtd_partition *onenand_parts,
+ u8 nr_parts, u8 cs)
+{
+ board_onenand_data.cs = cs;
+ board_onenand_data.parts = onenand_parts;
+ board_onenand_data.nr_parts = nr_parts;
+
+ gpmc_onenand_init(&board_onenand_data);
+}
+#else
+static void
+__init board_onenand_init(struct mtd_partition *nor_parts, u8 nr_parts, u8 cs)
+{
+}
+#endif /* CONFIG_MTD_ONENAND_OMAP2 || CONFIG_MTD_ONENAND_OMAP2_MODULE */
+
+#if defined(CONFIG_MTD_NAND_OMAP2) || \
+ defined(CONFIG_MTD_NAND_OMAP2_MODULE)
+
+/* Note that all values in this struct are in nanoseconds */
+static struct gpmc_timings nand_timings = {
+
+ .sync_clk = 0,
+
+ .cs_on = 0,
+ .cs_rd_off = 36,
+ .cs_wr_off = 36,
+
+ .adv_on = 6,
+ .adv_rd_off = 24,
+ .adv_wr_off = 36,
+
+ .we_off = 30,
+ .oe_off = 48,
+
+ .access = 54,
+ .rd_cycle = 72,
+ .wr_cycle = 72,
+
+ .wr_access = 30,
+ .wr_data_mux_bus = 0,
+};
+
+static struct omap_nand_platform_data board_nand_data = {
+ .nand_setup = NULL,
+ .gpmc_t = &nand_timings,
+ .dma_channel = -1, /* disable DMA in OMAP NAND driver */
+ .dev_ready = NULL,
+ .devsize = 0, /* '0' for 8-bit, '1' for 16-bit device */
+};
+
+void
+__init board_nand_init(struct mtd_partition *nand_parts, u8 nr_parts, u8 cs)
+{
+ board_nand_data.cs = cs;
+ board_nand_data.parts = nand_parts;
+ board_nand_data.nr_parts = nr_parts;
+
+ gpmc_nand_init(&board_nand_data);
+}
+#else
+void
+__init board_nand_init(struct mtd_partition *nand_parts, u8 nr_parts, u8 cs)
+{
+}
+#endif /* CONFIG_MTD_NAND_OMAP2 || CONFIG_MTD_NAND_OMAP2_MODULE */
+
+/**
+ * get_gpmc0_type - Reads the FPGA DIP_SWITCH_INPUT_REGISTER2 to get
+ * the various cs values.
+ */
+static u8 get_gpmc0_type(void)
+{
+ u8 cs = 0;
+ void __iomem *fpga_map_addr;
+
+ fpga_map_addr = ioremap(DEBUG_BASE, 4096);
+ if (!fpga_map_addr)
+ return -ENOMEM;
+
+ if (!(__raw_readw(fpga_map_addr + REG_FPGA_REV)))
+ /* we dont have an DEBUG FPGA??? */
+ /* Depend on #defines!! default to strata boot return param */
+ goto unmap;
+
+ /* S8-DIP-OFF = 1, S8-DIP-ON = 0 */
+ cs = __raw_readw(fpga_map_addr + REG_FPGA_DIP_SWITCH_INPUT2) & 0xf;
+
+ /* ES2.0 SDP's onwards 4 dip switches are provided for CS */
+ if (omap_rev() >= OMAP3430_REV_ES1_0)
+ /* change (S8-1:4=DS-2:0) to (S8-4:1=DS-2:0) */
+ cs = ((cs & 8) >> 3) | ((cs & 4) >> 1) |
+ ((cs & 2) << 1) | ((cs & 1) << 3);
+ else
+ /* change (S8-1:3=DS-2:0) to (S8-3:1=DS-2:0) */
+ cs = ((cs & 4) >> 2) | (cs & 2) | ((cs & 1) << 2);
+unmap:
+ iounmap(fpga_map_addr);
+ return cs;
+}
+
+/**
+ * sdp3430_flash_init - Identify devices connected to GPMC and register.
+ *
+ * @return - void.
+ */
+void board_flash_init(struct flash_partitions partition_info[],
+ char chip_sel_board[][GPMC_CS_NUM])
+{
+ u8 cs = 0;
+ u8 norcs = GPMC_CS_NUM + 1;
+ u8 nandcs = GPMC_CS_NUM + 1;
+ u8 onenandcs = GPMC_CS_NUM + 1;
+ u8 idx;
+ unsigned char *config_sel = NULL;
+
+ /* REVISIT: Is this return correct idx for 2430 SDP?
+ * for which cs configuration matches for 2430 SDP?
+ */
+ idx = get_gpmc0_type();
+ if (idx >= MAX_SUPPORTED_GPMC_CONFIG) {
+ printk(KERN_ERR "%s: Invalid chip select: %d\n", __func__, cs);
+ return;
+ }
+ config_sel = (unsigned char *)(chip_sel_board[idx]);
+
+ while (cs < GPMC_CS_NUM) {
+ switch (config_sel[cs]) {
+ case PDC_NOR:
+ if (norcs > GPMC_CS_NUM)
+ norcs = cs;
+ break;
+ case PDC_NAND:
+ if (nandcs > GPMC_CS_NUM)
+ nandcs = cs;
+ break;
+ case PDC_ONENAND:
+ if (onenandcs > GPMC_CS_NUM)
+ onenandcs = cs;
+ break;
+ };
+ cs++;
+ }
+
+ if (norcs > GPMC_CS_NUM)
+ printk(KERN_INFO "NOR: Unable to find configuration "
+ "in GPMC\n");
+ else
+ board_nor_init(partition_info[0].parts,
+ partition_info[0].nr_parts, norcs);
+
+ if (onenandcs > GPMC_CS_NUM)
+ printk(KERN_INFO "OneNAND: Unable to find configuration "
+ "in GPMC\n");
+ else
+ board_onenand_init(partition_info[1].parts,
+ partition_info[1].nr_parts, onenandcs);
+
+ if (nandcs > GPMC_CS_NUM)
+ printk(KERN_INFO "NAND: Unable to find configuration "
+ "in GPMC\n");
+ else
+ board_nand_init(partition_info[2].parts,
+ partition_info[2].nr_parts, nandcs);
+}
diff --git a/arch/arm/mach-omap2/board-sdp-flash.c b/arch/arm/mach-omap2/board-sdp-flash.c
deleted file mode 100755
index 2638c83..0000000
--- a/arch/arm/mach-omap2/board-sdp-flash.c
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- * board-sdp-flash.c
- * Modified from mach-omap2/board-3430sdp-flash.c
- *
- * Copyright (C) 2009 Nokia Corporation
- * Copyright (C) 2009 Texas Instruments
- *
- * Vimal Singh <vimalsingh@ti.com>
- *
- * 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.
- */
-
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/mtd/physmap.h>
-#include <linux/io.h>
-
-#include <plat/gpmc.h>
-#include <plat/nand.h>
-#include <plat/onenand.h>
-#include <plat/tc.h>
-#include <mach/board-sdp.h>
-
-#define REG_FPGA_REV 0x10
-#define REG_FPGA_DIP_SWITCH_INPUT2 0x60
-#define MAX_SUPPORTED_GPMC_CONFIG 3
-
-#define DEBUG_BASE 0x08000000 /* debug board */
-
-#define PDC_NOR 1
-#define PDC_NAND 2
-#define PDC_ONENAND 3
-#define DBG_MPDB 4
-
-/* various memory sizes */
-#define FLASH_SIZE_SDPV1 SZ_64M /* NOR flash (64 Meg aligned) */
-#define FLASH_SIZE_SDPV2 SZ_128M /* NOR flash (256 Meg aligned) */
-
-/*
- * SDP3430 V2 Board CS organization
- * Different from SDP3430 V1. Now 4 switches used to specify CS
- *
- * See also the Switch S8 settings in the comments.
- *
- * REVISIT: Add support for 2430 SDP
- */
-static const unsigned char chip_sel_sdp[][GPMC_CS_NUM] = {
- {PDC_NOR, PDC_NAND, PDC_ONENAND, DBG_MPDB, 0, 0, 0, 0}, /* S8:1111 */
- {PDC_ONENAND, PDC_NAND, PDC_NOR, DBG_MPDB, 0, 0, 0, 0}, /* S8:1110 */
- {PDC_NAND, PDC_ONENAND, PDC_NOR, DBG_MPDB, 0, 0, 0, 0}, /* S8:1101 */
-};
-
-static struct physmap_flash_data sdp_nor_data = {
- .width = 2,
-};
-
-static struct resource sdp_nor_resource = {
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device sdp_nor_device = {
- .name = "physmap-flash",
- .id = 0,
- .dev = {
- .platform_data = &sdp_nor_data,
- },
- .num_resources = 1,
- .resource = &sdp_nor_resource,
-};
-
-static void
-__init board_nor_init(struct flash_partitions sdp_nor_parts, u8 cs)
-{
- int err;
-
- sdp_nor_data.parts = sdp_nor_parts.parts;
- sdp_nor_data.nr_parts = sdp_nor_parts.nr_parts;
-
- /* Configure start address and size of NOR device */
- if (omap_rev() >= OMAP3430_REV_ES1_0) {
- err = gpmc_cs_request(cs, FLASH_SIZE_SDPV2 - 1,
- (unsigned long *)&sdp_nor_resource.start);
- sdp_nor_resource.end = sdp_nor_resource.start
- + FLASH_SIZE_SDPV2 - 1;
- } else {
- err = gpmc_cs_request(cs, FLASH_SIZE_SDPV1 - 1,
- (unsigned long *)&sdp_nor_resource.start);
- sdp_nor_resource.end = sdp_nor_resource.start
- + FLASH_SIZE_SDPV1 - 1;
- }
- if (err < 0) {
- printk(KERN_ERR "NOR: Can't request GPMC CS\n");
- return;
- }
- if (platform_device_register(&sdp_nor_device) < 0)
- printk(KERN_ERR "Unable to register NOR device\n");
-}
-
-#if defined(CONFIG_MTD_ONENAND_OMAP2) || \
- defined(CONFIG_MTD_ONENAND_OMAP2_MODULE)
-static struct omap_onenand_platform_data board_onenand_data = {
- .dma_channel = -1, /* disable DMA in OMAP OneNAND driver */
-};
-
-static void
-__init board_onenand_init(struct flash_partitions sdp_onenand_parts, u8 cs)
-{
- board_onenand_data.cs = cs;
- board_onenand_data.parts = sdp_onenand_parts.parts;
- board_onenand_data.nr_parts = sdp_onenand_parts.nr_parts;
-
- gpmc_onenand_init(&board_onenand_data);
-}
-#else
-static void
-__init board_onenand_init(struct flash_partitions sdp_onenand_parts, u8 cs)
-{
-}
-#endif /* CONFIG_MTD_ONENAND_OMAP2 || CONFIG_MTD_ONENAND_OMAP2_MODULE */
-
-#if defined(CONFIG_MTD_NAND_OMAP2) || \
- defined(CONFIG_MTD_NAND_OMAP2_MODULE)
-
-/* Note that all values in this struct are in nanoseconds */
-static struct gpmc_timings nand_timings = {
-
- .sync_clk = 0,
-
- .cs_on = 0,
- .cs_rd_off = 36,
- .cs_wr_off = 36,
-
- .adv_on = 6,
- .adv_rd_off = 24,
- .adv_wr_off = 36,
-
- .we_off = 30,
- .oe_off = 48,
-
- .access = 54,
- .rd_cycle = 72,
- .wr_cycle = 72,
-
- .wr_access = 30,
- .wr_data_mux_bus = 0,
-};
-
-static struct omap_nand_platform_data sdp_nand_data = {
- .nand_setup = NULL,
- .gpmc_t = &nand_timings,
- .dma_channel = -1, /* disable DMA in OMAP NAND driver */
- .dev_ready = NULL,
- .devsize = 0, /* '0' for 8-bit, '1' for 16-bit device */
-};
-
-static void
-__init board_nand_init(struct flash_partitions sdp_nand_parts, u8 cs)
-{
- sdp_nand_data.cs = cs;
- sdp_nand_data.parts = sdp_nand_parts.parts;
- sdp_nand_data.nr_parts = sdp_nand_parts.nr_parts;
-
- gpmc_nand_init(&sdp_nand_data);
-}
-#else
-static void
-__init board_nand_init(struct flash_partitions sdp_nand_parts, u8 cs)
-{
-}
-#endif /* CONFIG_MTD_NAND_OMAP2 || CONFIG_MTD_NAND_OMAP2_MODULE */
-
-/**
- * get_gpmc0_type - Reads the FPGA DIP_SWITCH_INPUT_REGISTER2 to get
- * the various cs values.
- */
-static u8 get_gpmc0_type(void)
-{
- u8 cs = 0;
- void __iomem *fpga_map_addr;
-
- fpga_map_addr = ioremap(DEBUG_BASE, 4096);
- if (!fpga_map_addr)
- return -ENOMEM;
-
- if (!(__raw_readw(fpga_map_addr + REG_FPGA_REV)))
- /* we dont have an DEBUG FPGA??? */
- /* Depend on #defines!! default to strata boot return param */
- goto unmap;
-
- /* S8-DIP-OFF = 1, S8-DIP-ON = 0 */
- cs = __raw_readw(fpga_map_addr + REG_FPGA_DIP_SWITCH_INPUT2) & 0xf;
-
- /* ES2.0 SDP's onwards 4 dip switches are provided for CS */
- if (omap_rev() >= OMAP3430_REV_ES1_0)
- /* change (S8-1:4=DS-2:0) to (S8-4:1=DS-2:0) */
- cs = ((cs & 8) >> 3) | ((cs & 4) >> 1) |
- ((cs & 2) << 1) | ((cs & 1) << 3);
- else
- /* change (S8-1:3=DS-2:0) to (S8-3:1=DS-2:0) */
- cs = ((cs & 4) >> 2) | (cs & 2) | ((cs & 1) << 2);
-unmap:
- iounmap(fpga_map_addr);
- return cs;
-}
-
-/**
- * sdp3430_flash_init - Identify devices connected to GPMC and register.
- *
- * @return - void.
- */
-void __init sdp_flash_init(struct flash_partitions sdp_partition_info[])
-{
- u8 cs = 0;
- u8 norcs = GPMC_CS_NUM + 1;
- u8 nandcs = GPMC_CS_NUM + 1;
- u8 onenandcs = GPMC_CS_NUM + 1;
- u8 idx;
- unsigned char *config_sel = NULL;
-
- /* REVISIT: Is this return correct idx for 2430 SDP?
- * for which cs configuration matches for 2430 SDP?
- */
- idx = get_gpmc0_type();
- if (idx >= MAX_SUPPORTED_GPMC_CONFIG) {
- printk(KERN_ERR "%s: Invalid chip select: %d\n", __func__, cs);
- return;
- }
- config_sel = (unsigned char *)(chip_sel_sdp[idx]);
-
- while (cs < GPMC_CS_NUM) {
- switch (config_sel[cs]) {
- case PDC_NOR:
- if (norcs > GPMC_CS_NUM)
- norcs = cs;
- break;
- case PDC_NAND:
- if (nandcs > GPMC_CS_NUM)
- nandcs = cs;
- break;
- case PDC_ONENAND:
- if (onenandcs > GPMC_CS_NUM)
- onenandcs = cs;
- break;
- };
- cs++;
- }
-
- if (norcs > GPMC_CS_NUM)
- printk(KERN_INFO "NOR: Unable to find configuration "
- "in GPMC\n");
- else
- board_nor_init(sdp_partition_info[0], norcs);
-
- if (onenandcs > GPMC_CS_NUM)
- printk(KERN_INFO "OneNAND: Unable to find configuration "
- "in GPMC\n");
- else
- board_onenand_init(sdp_partition_info[1], onenandcs);
-
- if (nandcs > GPMC_CS_NUM)
- printk(KERN_INFO "NAND: Unable to find configuration "
- "in GPMC\n");
- else
- board_nand_init(sdp_partition_info[2], nandcs);
-}
diff --git a/arch/arm/mach-omap2/include/mach/board-flash.h b/arch/arm/mach-omap2/include/mach/board-flash.h
new file mode 100644
index 0000000..b2242ae
--- /dev/null
+++ b/arch/arm/mach-omap2/include/mach/board-flash.h
@@ -0,0 +1,28 @@
+/*
+ * board-sdp.h
+ *
+ * Information structures for SDP-specific board config data
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ * Copyright (C) 2009 Texas Instruments
+ *
+ * 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.
+ */
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <plat/gpmc.h>
+
+#define PDC_NOR 1
+#define PDC_NAND 2
+#define PDC_ONENAND 3
+#define DBG_MPDB 4
+
+struct flash_partitions {
+ struct mtd_partition *parts;
+ int nr_parts;
+};
+
+extern void board_flash_init(struct flash_partitions [],
+ char chip_sel[][GPMC_CS_NUM]);
diff --git a/arch/arm/mach-omap2/include/mach/board-sdp.h b/arch/arm/mach-omap2/include/mach/board-sdp.h
deleted file mode 100644
index 465169c..0000000
--- a/arch/arm/mach-omap2/include/mach/board-sdp.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * board-sdp.h
- *
- * Information structures for SDP-specific board config data
- *
- * Copyright (C) 2009 Nokia Corporation
- * Copyright (C) 2009 Texas Instruments
- *
- * 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.
- */
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/partitions.h>
-
-struct flash_partitions {
- struct mtd_partition *parts;
- int nr_parts;
-};
-
-extern void sdp_flash_init(struct flash_partitions []);
--
1.5.4.7
^ permalink raw reply related [flat|nested] 102+ messages in thread
* [PATCH v3 2/8] omap3: add support for NAND on zoom2 board
2010-06-16 11:39 ` [PATCH v3 1/8] omap3 flash: rename board-sdp-flash.c to be use by other boards Sukumar Ghorai
@ 2010-06-16 11:39 ` Sukumar Ghorai
2010-06-16 11:39 ` [PATCH v3 3/8] omap3: add support for NAND on zoom3 board Sukumar Ghorai
2010-07-05 12:23 ` [PATCH v3 1/8] omap3 flash: rename board-sdp-flash.c to be use by other boards Tony Lindgren
1 sibling, 1 reply; 102+ messages in thread
From: Sukumar Ghorai @ 2010-06-16 11:39 UTC (permalink / raw)
To: linux-omap; +Cc: Sukumar Ghorai, Vimal Singh
This patch adds NAND support to ZOOM2 board.
Signed-off-by: Sukumar Ghorai <s-ghorai@ti.com>
Signed-off-by: Vimal Singh <vimalsingh@ti.com>
---
arch/arm/mach-omap2/Makefile | 1 +
arch/arm/mach-omap2/board-zoom2.c | 43 +++++++++++++++++++++++++
arch/arm/mach-omap2/include/mach/board-zoom.h | 6 +++
3 files changed, 50 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index 0d854f1..e7159b0 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -126,6 +126,7 @@ obj-$(CONFIG_MACH_NOKIA_RX51) += board-rx51.o \
hsmmc.o
obj-$(CONFIG_MACH_OMAP_ZOOM2) += board-zoom2.o \
board-zoom-peripherals.o \
+ board-flash.o \
hsmmc.o \
board-zoom-debugboard.o
obj-$(CONFIG_MACH_OMAP_ZOOM3) += board-zoom3.o \
diff --git a/arch/arm/mach-omap2/board-zoom2.c b/arch/arm/mach-omap2/board-zoom2.c
index 803ef14..549f274 100644
--- a/arch/arm/mach-omap2/board-zoom2.c
+++ b/arch/arm/mach-omap2/board-zoom2.c
@@ -77,10 +77,53 @@ static struct omap_board_mux board_mux[] __initdata = {
#define board_mux NULL
#endif
+static struct mtd_partition zoom_nand_partitions[] = {
+ /* All the partition sizes are listed in terms of NAND block size */
+ {
+ .name = "X-Loader-NAND",
+ .offset = 0,
+ .size = 4 * (64 * 2048), /* 512KB, 0x80000 */
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ {
+ .name = "U-Boot-NAND",
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x80000 */
+ .size = 10 * (64 * 2048), /* 1.25MB, 0x140000 */
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ {
+ .name = "Boot Env-NAND",
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x1c0000 */
+ .size = 2 * (64 * 2048), /* 256KB, 0x40000 */
+ },
+ {
+ .name = "Kernel-NAND",
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x0200000*/
+ .size = 240 * (64 * 2048), /* 30M, 0x1E00000 */
+ },
+ {
+ .name = "system",
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x2000000 */
+ .size = 3328 * (64 * 2048), /* 416M, 0x1A000000 */
+ },
+ {
+ .name = "userdata",
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x1C000000*/
+ .size = 256 * (64 * 2048), /* 32M, 0x2000000 */
+ },
+ {
+ .name = "cache",
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x1E000000*/
+ .size = 256 * (64 * 2048), /* 32M, 0x2000000 */
+ },
+};
+
static void __init omap_zoom2_init(void)
{
omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
zoom_peripherals_init();
+ board_nand_init(zoom_nand_partitions,
+ ARRAY_SIZE(zoom_nand_partitions), ZOOM_NAND_CS);
zoom_debugboard_init();
}
diff --git a/arch/arm/mach-omap2/include/mach/board-zoom.h b/arch/arm/mach-omap2/include/mach/board-zoom.h
index c93b29e..3af69d2 100644
--- a/arch/arm/mach-omap2/include/mach/board-zoom.h
+++ b/arch/arm/mach-omap2/include/mach/board-zoom.h
@@ -1,5 +1,11 @@
/*
* Defines for zoom boards
*/
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+
+#define ZOOM_NAND_CS 0
+
+extern void __init board_nand_init(struct mtd_partition *, u8 nr_parts, u8 cs);
extern int __init zoom_debugboard_init(void);
extern void __init zoom_peripherals_init(void);
^ permalink raw reply related [flat|nested] 102+ messages in thread
* [PATCH v3 3/8] omap3: add support for NAND on zoom3 board
2010-06-16 11:39 ` [PATCH v3 2/8] omap3: add support for NAND on zoom2 board Sukumar Ghorai
@ 2010-06-16 11:39 ` Sukumar Ghorai
2010-06-16 11:39 ` [PATCH v3 4/8] omap-3630-sdp : Add support for Flash Sukumar Ghorai
0 siblings, 1 reply; 102+ messages in thread
From: Sukumar Ghorai @ 2010-06-16 11:39 UTC (permalink / raw)
To: linux-omap; +Cc: Sukumar Ghorai, Vimal Singh
patch adds NAND support to zoom3 board.
Signed-off-by: Sukumar Ghorai <s-ghorai@ti.com>
Signed-off-by: Vimal Singh <vimalsingh@ti.com>
---
arch/arm/mach-omap2/Makefile | 1 +
arch/arm/mach-omap2/board-zoom3.c | 43 +++++++++++++++++++++++++++++++++++++
2 files changed, 44 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index e7159b0..00f4cfd 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -131,6 +131,7 @@ obj-$(CONFIG_MACH_OMAP_ZOOM2) += board-zoom2.o \
board-zoom-debugboard.o
obj-$(CONFIG_MACH_OMAP_ZOOM3) += board-zoom3.o \
board-zoom-peripherals.o \
+ board-flash.o \
hsmmc.o \
board-zoom-debugboard.o
obj-$(CONFIG_MACH_OMAP_3630SDP) += board-3630sdp.o \
diff --git a/arch/arm/mach-omap2/board-zoom3.c b/arch/arm/mach-omap2/board-zoom3.c
index 3314704..692c6c6 100644
--- a/arch/arm/mach-omap2/board-zoom3.c
+++ b/arch/arm/mach-omap2/board-zoom3.c
@@ -34,6 +34,47 @@ static void __init omap_zoom_map_io(void)
static struct omap_board_config_kernel zoom_config[] __initdata = {
};
+static struct mtd_partition zoom_nand_partitions[] = {
+ /* All the partition sizes are listed in terms of NAND block size */
+ {
+ .name = "X-Loader-NAND",
+ .offset = 0,
+ .size = 4 * (64 * 2048), /* 512KB, 0x80000 */
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ {
+ .name = "U-Boot-NAND",
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x80000 */
+ .size = 10 * (64 * 2048), /* 1.25MB, 0x140000 */
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ {
+ .name = "Boot Env-NAND",
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x1c0000 */
+ .size = 2 * (64 * 2048), /* 256KB, 0x40000 */
+ },
+ {
+ .name = "Kernel-NAND",
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x0200000*/
+ .size = 240 * (64 * 2048), /* 30M, 0x1E00000 */
+ },
+ {
+ .name = "system",
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x2000000 */
+ .size = 3328 * (64 * 2048), /* 416M, 0x1A000000 */
+ },
+ {
+ .name = "userdata",
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x1C000000*/
+ .size = 256 * (64 * 2048), /* 32M, 0x2000000 */
+ },
+ {
+ .name = "cache",
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x1E000000*/
+ .size = 256 * (64 * 2048), /* 32M, 0x2000000 */
+ },
+};
+
static void __init omap_zoom_init_irq(void)
{
omap_board_config = zoom_config;
@@ -66,6 +107,8 @@ static void __init omap_zoom_init(void)
{
omap3_mux_init(board_mux, OMAP_PACKAGE_CBP);
zoom_peripherals_init();
+ board_nand_init(zoom_nand_partitions,
+ ARRAY_SIZE(zoom_nand_partitions), ZOOM_NAND_CS);
zoom_debugboard_init();
omap_mux_init_gpio(64, OMAP_PIN_OUTPUT);
^ permalink raw reply related [flat|nested] 102+ messages in thread
* [PATCH v3 4/8] omap-3630-sdp : Add support for Flash
2010-06-16 11:39 ` [PATCH v3 3/8] omap3: add support for NAND on zoom3 board Sukumar Ghorai
@ 2010-06-16 11:39 ` Sukumar Ghorai
2010-06-16 11:39 ` [PATCH v3 5/8] omap3: add support for NAND on LDP board Sukumar Ghorai
0 siblings, 1 reply; 102+ messages in thread
From: Sukumar Ghorai @ 2010-06-16 11:39 UTC (permalink / raw)
To: linux-omap; +Cc: Sukumar Ghorai
add support for NAND, OneNAND, NOR on omap 3630-sdp board.
Signed-off-by: Sukumar Ghorai <s-ghorai@ti.com>
---
arch/arm/mach-omap2/Makefile | 1 +
arch/arm/mach-omap2/board-3630sdp.c | 120 +++++++++++++++++++++++++++++++++++
2 files changed, 121 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index a795eb6..400f9cf
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -133,6 +133,7 @@ obj-$(CONFIG_MACH_OMAP_ZOOM3) += board-zoom3.o \
board-zoom-debugboard.o
obj-$(CONFIG_MACH_OMAP_3630SDP) += board-3630sdp.o \
board-zoom-peripherals.o \
+ board-flash.o \
hsmmc.o
obj-$(CONFIG_MACH_CM_T35) += board-cm-t35.o \
hsmmc.o
diff --git a/arch/arm/mach-omap2/board-3630sdp.c b/arch/arm/mach-omap2/board-3630sdp.c
index 504d2bd..a3f24cb
--- a/arch/arm/mach-omap2/board-3630sdp.c
+++ b/arch/arm/mach-omap2/board-3630sdp.c
@@ -22,6 +22,7 @@
#include <plat/usb.h>
#include <mach/board-zoom.h>
+#include <mach/board-flash.h>
#include "mux.h"
#include "sdram-hynix-h8mbx00u0mer-0em.h"
@@ -93,12 +94,131 @@ static struct omap_board_mux board_mux[] __initdata = {
#define board_mux NULL
#endif
+/*
+ * SDP3630 CS organization
+ * See also the Switch S8 settings in the comments.
+ */
+static char chip_sel_sdp[][GPMC_CS_NUM] = {
+ {PDC_NOR, PDC_NAND, PDC_ONENAND, DBG_MPDB, 0, 0, 0, 0}, /* S8:1111 */
+ {PDC_ONENAND, PDC_NAND, PDC_NOR, DBG_MPDB, 0, 0, 0, 0}, /* S8:1110 */
+ {PDC_NAND, PDC_ONENAND, PDC_NOR, DBG_MPDB, 0, 0, 0, 0}, /* S8:1101 */
+};
+
+static struct mtd_partition sdp_nor_partitions[] = {
+ /* bootloader (U-Boot, etc) in first sector */
+ {
+ .name = "Bootloader-NOR",
+ .offset = 0,
+ .size = SZ_256K,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ /* bootloader params in the next sector */
+ {
+ .name = "Params-NOR",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_256K,
+ .mask_flags = 0,
+ },
+ /* kernel */
+ {
+ .name = "Kernel-NOR",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_2M,
+ .mask_flags = 0
+ },
+ /* file system */
+ {
+ .name = "Filesystem-NOR",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ .mask_flags = 0
+ }
+};
+
+static struct mtd_partition sdp_onenand_partitions[] = {
+ {
+ .name = "X-Loader-OneNAND",
+ .offset = 0,
+ .size = 4 * (64 * 2048),
+ .mask_flags = MTD_WRITEABLE /* force read-only */
+ },
+ {
+ .name = "U-Boot-OneNAND",
+ .offset = MTDPART_OFS_APPEND,
+ .size = 2 * (64 * 2048),
+ .mask_flags = MTD_WRITEABLE /* force read-only */
+ },
+ {
+ .name = "U-Boot Environment-OneNAND",
+ .offset = MTDPART_OFS_APPEND,
+ .size = 1 * (64 * 2048),
+ },
+ {
+ .name = "Kernel-OneNAND",
+ .offset = MTDPART_OFS_APPEND,
+ .size = 16 * (64 * 2048),
+ },
+ {
+ .name = "File System-OneNAND",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ },
+};
+
+static struct mtd_partition sdp_nand_partitions[] = {
+ /* All the partition sizes are listed in terms of NAND block size */
+ {
+ .name = "X-Loader-NAND",
+ .offset = 0,
+ .size = 4 * (64 * 2048),
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ {
+ .name = "U-Boot-NAND",
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x80000 */
+ .size = 10 * (64 * 2048),
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ {
+ .name = "Boot Env-NAND",
+
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x1c0000 */
+ .size = 6 * (64 * 2048),
+ },
+ {
+ .name = "Kernel-NAND",
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x280000 */
+ .size = 40 * (64 * 2048),
+ },
+ {
+ .name = "File System - NAND",
+ .size = MTDPART_SIZ_FULL,
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x780000 */
+ },
+};
+
+static struct flash_partitions sdp_flash_partitions[] = {
+ {
+ .parts = sdp_nor_partitions,
+ .nr_parts = ARRAY_SIZE(sdp_nor_partitions),
+ },
+ {
+ .parts = sdp_onenand_partitions,
+ .nr_parts = ARRAY_SIZE(sdp_onenand_partitions),
+ },
+ {
+ .parts = sdp_nand_partitions,
+ .nr_parts = ARRAY_SIZE(sdp_nand_partitions),
+ },
+};
+
static void __init omap_sdp_init(void)
{
omap3_mux_init(board_mux, OMAP_PACKAGE_CBP);
omap_serial_init();
zoom_peripherals_init();
board_smc91x_init();
+ board_flash_init(sdp_flash_partitions, chip_sel_sdp);
enable_board_wakeup_source();
usb_ehci_init(&ehci_pdata);
}
--
1.5.4.7
^ permalink raw reply related [flat|nested] 102+ messages in thread
* [PATCH v3 5/8] omap3: add support for NAND on LDP board
2010-06-16 11:39 ` [PATCH v3 4/8] omap-3630-sdp : Add support for Flash Sukumar Ghorai
@ 2010-06-16 11:39 ` Sukumar Ghorai
2010-06-16 11:39 ` [PATCH v3 6/8] omap-3630-sdp: enable Flash device support Sukumar Ghorai
0 siblings, 1 reply; 102+ messages in thread
From: Sukumar Ghorai @ 2010-06-16 11:39 UTC (permalink / raw)
To: linux-omap; +Cc: Sukumar Ghorai, Vimal Singh
patch adds NAND support to LDP board.
Signed-off-by: Vimal Singh <vimalsingh@ti.com>
Signed-off-by: Sukumar Ghorai <s-ghorai@ti.com>
---
arch/arm/mach-omap2/Makefile | 1 +
arch/arm/mach-omap2/board-ldp.c | 35 +++++++++++++++++++++++++++++++++++
2 files changed, 36 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index 6c67126..af715fa 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -108,6 +108,7 @@ obj-$(CONFIG_MACH_OMAP3_BEAGLE) += board-omap3beagle.o \
obj-$(CONFIG_MACH_DEVKIT8000) += board-devkit8000.o \
hsmmc.o
obj-$(CONFIG_MACH_OMAP_LDP) += board-ldp.o \
+ board-flash.o \
hsmmc.o
obj-$(CONFIG_MACH_OVERO) += board-overo.o \
hsmmc.o
diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c
index fefd7e6..778afab 100644
--- a/arch/arm/mach-omap2/board-ldp.c
+++ b/arch/arm/mach-omap2/board-ldp.c
@@ -38,6 +38,7 @@
#include <plat/board.h>
#include <plat/common.h>
#include <plat/gpmc.h>
+#include <mach/board-zoom.h>
#include <asm/delay.h>
#include <plat/control.h>
@@ -388,6 +389,38 @@ static struct omap_musb_board_data musb_board_data = {
.power = 100,
};
+static struct mtd_partition ldp_nand_partitions[] = {
+ /* All the partition sizes are listed in terms of NAND block size */
+ {
+ .name = "X-Loader-NAND",
+ .offset = 0,
+ .size = 4 * (64 * 2048), /* 512KB, 0x80000 */
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ {
+ .name = "U-Boot-NAND",
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x80000 */
+ .size = 10 * (64 * 2048), /* 1.25MB, 0x140000 */
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ {
+ .name = "Boot Env-NAND",
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x1c0000 */
+ .size = 2 * (64 * 2048), /* 256KB, 0x40000 */
+ },
+ {
+ .name = "Kernel-NAND",
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x0200000*/
+ .size = 240 * (64 * 2048), /* 30M, 0x1E00000 */
+ },
+ {
+ .name = "File System - NAND",
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x2000000 */
+ .size = MTDPART_SIZ_FULL, /* 96MB, 0x6000000 */
+ },
+
+};
+
static void __init omap_ldp_init(void)
{
omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
@@ -400,6 +433,8 @@ static void __init omap_ldp_init(void)
ads7846_dev_init();
omap_serial_init();
usb_musb_init(&musb_board_data);
+ board_nand_init(ldp_nand_partitions,
+ ARRAY_SIZE(ldp_nand_partitions), ZOOM_NAND_CS);
omap2_hsmmc_init(mmc);
/* link regulators to MMC adapters */
^ permalink raw reply related [flat|nested] 102+ messages in thread
* [PATCH v3 6/8] omap-3630-sdp: enable Flash device support
2010-06-16 11:39 ` [PATCH v3 5/8] omap3: add support for NAND on LDP board Sukumar Ghorai
@ 2010-06-16 11:39 ` Sukumar Ghorai
2010-06-16 11:39 ` [PATCH v3 7/8] zoom2: enable NAND support Sukumar Ghorai
2010-07-05 12:27 ` [PATCH v3 6/8] omap-3630-sdp: enable Flash device support Tony Lindgren
0 siblings, 2 replies; 102+ messages in thread
From: Sukumar Ghorai @ 2010-06-16 11:39 UTC (permalink / raw)
To: linux-omap; +Cc: Sukumar Ghorai
update config file to support for NAND, OneNAND, NOR on omap 3630-sdp board.
Signed-off-by: Sukumar Ghorai <s-ghorai@ti.com>
---
arch/arm/configs/omap_3630sdp_defconfig | 31 ++++++++++++++++++++++++++++++-
1 files changed, 30 insertions(+), 1 deletions(-)
diff --git a/arch/arm/configs/omap_3630sdp_defconfig b/arch/arm/configs/omap_3630sdp_defconfig
index 609f348..8c75c19
--- a/arch/arm/configs/omap_3630sdp_defconfig
+++ b/arch/arm/configs/omap_3630sdp_defconfig
@@ -461,7 +461,29 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_SYS_HYPERVISOR is not set
CONFIG_CONNECTOR=y
CONFIG_PROC_EVENTS=y
-# CONFIG_MTD is not set
+CONFIG_MTD=y
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_GEN_PROBE=y
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_UTIL=y
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_OMAP2=y
+CONFIG_MTD_NAND_OMAP_PREFETCH=y
+CONFIG_MTD_NAND_IDS=y
+CONFIG_MTD_ONENAND=y
+CONFIG_MTD_ONENAND_OMAP2=y
# CONFIG_PARPORT is not set
CONFIG_BLK_DEV=y
# CONFIG_BLK_DEV_COW_COMMON is not set
@@ -1310,6 +1332,13 @@ CONFIG_MISC_FILESYSTEMS=y
# CONFIG_BEFS_FS is not set
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+CONFIG_JFFS2_CMODE_PRIORITY=y
# CONFIG_CRAMFS is not set
# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
--
1.5.4.7
^ permalink raw reply related [flat|nested] 102+ messages in thread
* [PATCH v3 7/8] zoom2: enable NAND support
2010-06-16 11:39 ` [PATCH v3 6/8] omap-3630-sdp: enable Flash device support Sukumar Ghorai
@ 2010-06-16 11:39 ` Sukumar Ghorai
2010-06-16 11:40 ` [PATCH v3 8/8] zoom3: " Sukumar Ghorai
2010-07-05 12:27 ` [PATCH v3 6/8] omap-3630-sdp: enable Flash device support Tony Lindgren
1 sibling, 1 reply; 102+ messages in thread
From: Sukumar Ghorai @ 2010-06-16 11:39 UTC (permalink / raw)
To: linux-omap; +Cc: Sukumar Ghorai
update config file to support for NAND in zoom2.
Signed-off-by: Sukumar Ghorai <s-ghorai@ti.com>
---
arch/arm/configs/omap_zoom2_defconfig | 24 +++++++++++++++++++++++-
1 files changed, 23 insertions(+), 1 deletions(-)
arch/arm/configs/omap_zoom2_defconfig
diff --git a/arch/arm/configs/omap_zoom2_defconfig b/arch/arm/configs/omap_zoom2_defconfig
index 881faea..ec58688
--- a/arch/arm/configs/omap_zoom2_defconfig
+++ b/arch/arm/configs/omap_zoom2_defconfig
@@ -440,7 +440,22 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_SYS_HYPERVISOR is not set
CONFIG_CONNECTOR=y
CONFIG_PROC_EVENTS=y
-# CONFIG_MTD is not set
+CONFIG_MTD=y
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_OMAP2=y
+CONFIG_MTD_NAND_OMAP_PREFETCH=y
+CONFIG_MTD_NAND_IDS=y
# CONFIG_PARPORT is not set
CONFIG_BLK_DEV=y
# CONFIG_BLK_DEV_COW_COMMON is not set
@@ -1248,6 +1263,13 @@ CONFIG_MISC_FILESYSTEMS=y
# CONFIG_BEFS_FS is not set
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+CONFIG_JFFS2_CMODE_PRIORITY=y
# CONFIG_CRAMFS is not set
# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
--
1.5.4.7
^ permalink raw reply related [flat|nested] 102+ messages in thread
* [PATCH v3 8/8] zoom3: enable NAND support
2010-06-16 11:39 ` [PATCH v3 7/8] zoom2: enable NAND support Sukumar Ghorai
@ 2010-06-16 11:40 ` Sukumar Ghorai
0 siblings, 0 replies; 102+ messages in thread
From: Sukumar Ghorai @ 2010-06-16 11:40 UTC (permalink / raw)
To: linux-omap; +Cc: Sukumar Ghorai
update config file to support for NAND on zoom3 board.
Signed-off-by: Sukumar Ghorai <s-ghorai@ti.com>
---
arch/arm/configs/omap_zoom3_defconfig | 24 +++++++++++++++++++++++-
1 files changed, 23 insertions(+), 1 deletions(-)
arch/arm/configs/omap_zoom3_defconfig
diff --git a/arch/arm/configs/omap_zoom3_defconfig b/arch/arm/configs/omap_zoom3_defconfig
index 5e55b55..e3e53cd
--- a/arch/arm/configs/omap_zoom3_defconfig
+++ b/arch/arm/configs/omap_zoom3_defconfig
@@ -461,7 +461,22 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_SYS_HYPERVISOR is not set
CONFIG_CONNECTOR=y
CONFIG_PROC_EVENTS=y
-# CONFIG_MTD is not set
+CONFIG_MTD=y
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_OMAP2=y
+CONFIG_MTD_NAND_OMAP_PREFETCH=y
+CONFIG_MTD_NAND_IDS=y
# CONFIG_PARPORT is not set
CONFIG_BLK_DEV=y
# CONFIG_BLK_DEV_COW_COMMON is not set
@@ -1311,6 +1326,13 @@ CONFIG_MISC_FILESYSTEMS=y
# CONFIG_BEFS_FS is not set
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+CONFIG_JFFS2_CMODE_PRIORITY=y
# CONFIG_CRAMFS is not set
# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
--
1.5.4.7
^ permalink raw reply related [flat|nested] 102+ messages in thread
* RE: [PATCH v5 0/3] omap3 nand: cleanup exiting platform related code
2010-06-08 17:12 ` [PATCH v5 0/3] omap3 nand: cleanup exiting platform related code Vimal Singh
2010-06-15 13:26 ` Ghorai, Sukumar
@ 2010-06-30 14:42 ` Ghorai, Sukumar
1 sibling, 0 replies; 102+ messages in thread
From: Ghorai, Sukumar @ 2010-06-30 14:42 UTC (permalink / raw)
To: Tony Lindgren
Cc: linux-omap@vger.kernel.org, linux-mtd@lists.infradead.org,
mike@compulab.co.il, Vimal Singh
Tony,
Please let me know if any have input on following two series.
http://www.mail-archive.com/linux-omap@vger.kernel.org/msg30305.html
http://www.mail-archive.com/linux-omap@vger.kernel.org/msg30735.html
Regards,
Ghorai
> -----Original Message-----
> From: Ghorai, Sukumar
> Sent: Tuesday, June 15, 2010 6:57 PM
> To: 'Tony Lindgren'
> Cc: linux-omap@vger.kernel.org; linux-mtd@lists.infradead.org;
> tony@atomide.com; mike@compulab.co.il; 'Vimal Singh'
> Subject: RE: [PATCH v5 0/3] omap3 nand: cleanup exiting platform related
> code
>
> Tony,
>
> > -----Original Message-----
> > From: Vimal Singh [mailto:vimal.newwork@gmail.com]
> > Sent: Tuesday, June 08, 2010 10:43 PM
> > To: Ghorai, Sukumar
> > Cc: linux-omap@vger.kernel.org; linux-mtd@lists.infradead.org;
> > tony@atomide.com; mike@compulab.co.il
> > Subject: Re: [PATCH v5 0/3] omap3 nand: cleanup exiting platform related
> > code
> >
> > Reviewed-by: Vimal Singh <vimal.newwork@gmail.com>
> >
> > On Fri, Jun 4, 2010 at 1:10 PM, Sukumar Ghorai <s-ghorai@ti.com> wrote:
> > > The following set of patches applies on top of for-next branch.
> > > http://git.kernel.org/?p=linux/kernel/git/tmlind/linux-omap-
> > 2.6.git
> > > Patches verified on: omap3430-SDP, omap3630-sdp, zoom3 and beagle
> > board
> > >
> > > And these are the patches required to address the following input -
> > > 1. The NAND driver needs to stop tinkering with the GPMC registers
> > > The omap General Purpose Memory Controller (GPMC) registers are
> > omap
> > > specific, and not driver specific. Tinkering with these
> registers
> > can
> > > cause issues with the other devices on the GPMC.
> > >
> > > 2. Passing hardcoded GPMC_CS0_BASE needs to go from the board
> files
> > > Passing hardcoded GPMC virtual addressess is sure way to mess
> up
> > things.
> > > This should all become unnecessary once the NAND drivers stops
> > messing
> > > with the GPMC registers directly.
> > > Discussion: http://www.mail-archive.com/linux-
> > omap@vger.kernel.org/msg27630.html
> > >
> > > Changes in this series -
> > > Unused function removed.
> > >
> > > Functions related to ecc and prefetch engine are optimized.
> > > v4: http://www.mail-archive.com/linux-
> > omap@vger.kernel.org/msg29458.html
> > >
> > > Few functionality was missing like - There should be some locking as
> > only
> > > one chipselect can use the ECC or prefetch engine at a time. If you
> > have
> > > NAND in two chipselects, bad things would happen.
> > > v3: http://www.mail-archive.com/linux-
> > omap@vger.kernel.org/msg28715.html
> > >
> > > Additionally, it was needed to implement more functions for the
> > platform
> > > init code to use.
> > > v2: http://www.mail-archive.com/linux-
> > omap@vger.kernel.org/msg28467.html
> > >
> > > v1: http://www.mail-archive.com/linux-
> > omap@vger.kernel.org/msg28164.html
> > >
> > >
> > > Sukumar Ghorai (3):
> > > omap3 gpmc: functionality enhancement
> > > omap3 nand: cleanup virtual address usages
> > > omap3 nand: fix issue in board file to detect nand
> > > arch/arm/mach-omap2/board-cm-t35.c | 20 +---
> > > arch/arm/mach-omap2/board-devkit8000.c | 25 +---
> > > arch/arm/mach-omap2/board-omap3beagle.c | 24 +---
> > > arch/arm/mach-omap2/board-omap3touchbook.c | 25 +---
> > > arch/arm/mach-omap2/board-overo.c | 24 +---
> > > arch/arm/mach-omap2/board-sdp-flash.c | 5 -
> > > arch/arm/mach-omap2/gpmc-nand.c | 39 ++----
> > > arch/arm/mach-omap2/gpmc.c | 228
> > +++++++++++++++++++++++++---
> > > arch/arm/plat-omap/include/plat/gpmc.h | 36 ++++-
> > > arch/arm/plat-omap/include/plat/nand.h | 6 +-
> > > drivers/mtd/nand/omap2.c | 229 ++++++++-----------
> --
> > -------
> > > 11 files changed, 320 insertions(+), 341 deletions(-)
>
> [Ghorai] Any comments or input on these patch?
>
> > >
> > > --
> > > To unsubscribe from this list: send the line "unsubscribe linux-omap"
> in
> > > the body of a message to majordomo@vger.kernel.org
> > > More majordomo info at http://vger.kernel.org/majordomo-info.html
> > >
> >
> >
> >
> > --
> > Regards,
> > Vimal Singh
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 102+ messages in thread
* Re: [PATCH v3 1/8] omap3 flash: rename board-sdp-flash.c to be use by other boards
2010-06-16 11:39 ` [PATCH v3 1/8] omap3 flash: rename board-sdp-flash.c to be use by other boards Sukumar Ghorai
2010-06-16 11:39 ` [PATCH v3 2/8] omap3: add support for NAND on zoom2 board Sukumar Ghorai
@ 2010-07-05 12:23 ` Tony Lindgren
2010-07-06 6:05 ` Shilimkar, Santosh
1 sibling, 1 reply; 102+ messages in thread
From: Tony Lindgren @ 2010-07-05 12:23 UTC (permalink / raw)
To: Sukumar Ghorai; +Cc: linux-omap
* Sukumar Ghorai <s-ghorai@ti.com> [100616 14:34]:
> rename board-sdp-flash.c(board-flash.c) and board-sdp.h(board-flash.h) to
> used by other board e.g. zoom
>
> Signed-off-by: Sukumar Ghorai <s-ghorai@ti.com>
> ---
> arch/arm/mach-omap2/Makefile | 2 +-
> arch/arm/mach-omap2/board-3430sdp.c | 16 ++-
> arch/arm/mach-omap2/board-flash.c | 253 ++++++++++++++++++++++
> arch/arm/mach-omap2/board-sdp-flash.c | 267 ------------------------
> arch/arm/mach-omap2/include/mach/board-flash.h | 28 +++
> arch/arm/mach-omap2/include/mach/board-sdp.h | 21 --
> 6 files changed, 296 insertions(+), 291 deletions(-)
> create mode 100755 arch/arm/mach-omap2/board-flash.c
> delete mode 100755 arch/arm/mach-omap2/board-sdp-flash.c
> create mode 100644 arch/arm/mach-omap2/include/mach/board-flash.h
> delete mode 100644 arch/arm/mach-omap2/include/mach/board-sdp.h
Looks like this one won't apply:
patching file arch/arm/mach-omap2/board-sdp-flash.c
Hunk #1 FAILED at 1.
File arch/arm/mach-omap2/board-sdp-flash.c is not empty after patch, as expected
Regards,
Tony
^ permalink raw reply [flat|nested] 102+ messages in thread
* Re: [PATCH v3 6/8] omap-3630-sdp: enable Flash device support
2010-06-16 11:39 ` [PATCH v3 6/8] omap-3630-sdp: enable Flash device support Sukumar Ghorai
2010-06-16 11:39 ` [PATCH v3 7/8] zoom2: enable NAND support Sukumar Ghorai
@ 2010-07-05 12:27 ` Tony Lindgren
2010-07-06 5:23 ` Ghorai, Sukumar
1 sibling, 1 reply; 102+ messages in thread
From: Tony Lindgren @ 2010-07-05 12:27 UTC (permalink / raw)
To: Sukumar Ghorai; +Cc: linux-omap
* Sukumar Ghorai <s-ghorai@ti.com> [100616 14:34]:
> update config file to support for NAND, OneNAND, NOR on omap 3630-sdp board.
Let's drop all the defconfig changes from this series, we won't
be patching the defconfigs any longer as requested by Linus.
Regards,
Tony
^ permalink raw reply [flat|nested] 102+ messages in thread
* RE: [PATCH v3 6/8] omap-3630-sdp: enable Flash device support
2010-07-05 12:27 ` [PATCH v3 6/8] omap-3630-sdp: enable Flash device support Tony Lindgren
@ 2010-07-06 5:23 ` Ghorai, Sukumar
0 siblings, 0 replies; 102+ messages in thread
From: Ghorai, Sukumar @ 2010-07-06 5:23 UTC (permalink / raw)
To: Tony Lindgren; +Cc: linux-omap@vger.kernel.org
Tony,
> -----Original Message-----
> From: Tony Lindgren [mailto:tony@atomide.com]
> Sent: Monday, July 05, 2010 5:57 PM
> To: Ghorai, Sukumar
> Cc: linux-omap@vger.kernel.org
> Subject: Re: [PATCH v3 6/8] omap-3630-sdp: enable Flash device support
>
> * Sukumar Ghorai <s-ghorai@ti.com> [100616 14:34]:
> > update config file to support for NAND, OneNAND, NOR on omap 3630-sdp
> board.
>
> Let's drop all the defconfig changes from this series, we won't
> be patching the defconfigs any longer as requested by Linus.
[Ghorai] That's fine.
Regards,
Ghorai
>
> Regards,
>
> Tony
^ permalink raw reply [flat|nested] 102+ messages in thread
* RE: [PATCH v3 1/8] omap3 flash: rename board-sdp-flash.c to be use by other boards
2010-07-05 12:23 ` [PATCH v3 1/8] omap3 flash: rename board-sdp-flash.c to be use by other boards Tony Lindgren
@ 2010-07-06 6:05 ` Shilimkar, Santosh
2010-07-06 6:27 ` Ghorai, Sukumar
0 siblings, 1 reply; 102+ messages in thread
From: Shilimkar, Santosh @ 2010-07-06 6:05 UTC (permalink / raw)
To: Tony Lindgren, Ghorai, Sukumar; +Cc: linux-omap@vger.kernel.org
Sukumar,
> -----Original Message-----
> From: linux-omap-owner@vger.kernel.org [mailto:linux-omap-
> owner@vger.kernel.org] On Behalf Of Tony Lindgren
> Sent: Monday, July 05, 2010 5:53 PM
> To: Ghorai, Sukumar
> Cc: linux-omap@vger.kernel.org
> Subject: Re: [PATCH v3 1/8] omap3 flash: rename board-sdp-flash.c to be
> use by other boards
>
> * Sukumar Ghorai <s-ghorai@ti.com> [100616 14:34]:
> > rename board-sdp-flash.c(board-flash.c) and board-sdp.h(board-flash.h)
> to
> > used by other board e.g. zoom
> >
> > Signed-off-by: Sukumar Ghorai <s-ghorai@ti.com>
> > ---
> > arch/arm/mach-omap2/Makefile | 2 +-
> > arch/arm/mach-omap2/board-3430sdp.c | 16 ++-
> > arch/arm/mach-omap2/board-flash.c | 253
> ++++++++++++++++++++++
> > arch/arm/mach-omap2/board-sdp-flash.c | 267 -----------------
> -------
> > arch/arm/mach-omap2/include/mach/board-flash.h | 28 +++
> > arch/arm/mach-omap2/include/mach/board-sdp.h | 21 --
> > 6 files changed, 296 insertions(+), 291 deletions(-)
> > create mode 100755 arch/arm/mach-omap2/board-flash.c
> > delete mode 100755 arch/arm/mach-omap2/board-sdp-flash.c
> > create mode 100644 arch/arm/mach-omap2/include/mach/board-flash.h
> > delete mode 100644 arch/arm/mach-omap2/include/mach/board-sdp.h
>
> Looks like this one won't apply:
>
> patching file arch/arm/mach-omap2/board-sdp-flash.c
> Hunk #1 FAILED at 1.
> File arch/arm/mach-omap2/board-sdp-flash.c is not empty after patch, as
> expected
>
Try "git format-patch -M " when creating renaming patch.
Regards,
Santosh
^ permalink raw reply [flat|nested] 102+ messages in thread
* RE: [PATCH v3 1/8] omap3 flash: rename board-sdp-flash.c to be use by other boards
2010-07-06 6:05 ` Shilimkar, Santosh
@ 2010-07-06 6:27 ` Ghorai, Sukumar
0 siblings, 0 replies; 102+ messages in thread
From: Ghorai, Sukumar @ 2010-07-06 6:27 UTC (permalink / raw)
To: Tony Lindgren; +Cc: linux-omap@vger.kernel.org, Shilimkar, Santosh
[-- Attachment #1: Type: text/plain, Size: 2146 bytes --]
Tony,
> -----Original Message-----
> From: Shilimkar, Santosh
> Sent: Tuesday, July 06, 2010 11:35 AM
> To: Tony Lindgren; Ghorai, Sukumar
> Cc: linux-omap@vger.kernel.org
> Subject: RE: [PATCH v3 1/8] omap3 flash: rename board-sdp-flash.c to be
> use by other boards
>
> Sukumar,
> > -----Original Message-----
> > From: linux-omap-owner@vger.kernel.org [mailto:linux-omap-
> > owner@vger.kernel.org] On Behalf Of Tony Lindgren
> > Sent: Monday, July 05, 2010 5:53 PM
> > To: Ghorai, Sukumar
> > Cc: linux-omap@vger.kernel.org
> > Subject: Re: [PATCH v3 1/8] omap3 flash: rename board-sdp-flash.c to be
> > use by other boards
> >
> > * Sukumar Ghorai <s-ghorai@ti.com> [100616 14:34]:
> > > rename board-sdp-flash.c(board-flash.c) and board-sdp.h(board-flash.h)
> > to
> > > used by other board e.g. zoom
> > >
> > > Signed-off-by: Sukumar Ghorai <s-ghorai@ti.com>
> > > ---
> > > arch/arm/mach-omap2/Makefile | 2 +-
> > > arch/arm/mach-omap2/board-3430sdp.c | 16 ++-
> > > arch/arm/mach-omap2/board-flash.c | 253
> > ++++++++++++++++++++++
> > > arch/arm/mach-omap2/board-sdp-flash.c | 267 ---------------
> --
> > -------
> > > arch/arm/mach-omap2/include/mach/board-flash.h | 28 +++
> > > arch/arm/mach-omap2/include/mach/board-sdp.h | 21 --
> > > 6 files changed, 296 insertions(+), 291 deletions(-)
> > > create mode 100755 arch/arm/mach-omap2/board-flash.c
> > > delete mode 100755 arch/arm/mach-omap2/board-sdp-flash.c
> > > create mode 100644 arch/arm/mach-omap2/include/mach/board-flash.h
> > > delete mode 100644 arch/arm/mach-omap2/include/mach/board-sdp.h
> >
> > Looks like this one won't apply:
> >
> > patching file arch/arm/mach-omap2/board-sdp-flash.c
> > Hunk #1 FAILED at 1.
> > File arch/arm/mach-omap2/board-sdp-flash.c is not empty after patch, as
> > expected
> >
> Try "git format-patch -M " when creating renaming patch.
>
[Ghorai] Thanks Tony & Santosh.. And I think I understood the problem of my format-patch option. Please check with the attached patch(updated).
Regards,
Ghorai
[-- Attachment #2: 0001-omap3-flash-rename-board-sdp-flash.c-to-be-use-by-o.patch --]
[-- Type: application/octet-stream, Size: 10249 bytes --]
From 3ceba15a5e91c383ecda8ff2db396305b24d14e0 Mon Sep 17 00:00:00 2001
From: Sukumar Ghorai <s-ghorai@ti.com>
Date: Wed, 16 Jun 2010 16:10:58 +0530
Subject: [PATCH] omap3 flash: rename board-sdp-flash.c to be use by other boards
rename board-sdp-flash.c(board-flash.c) and board-sdp.h(board-flash.h) to
used by other board e.g. zoom
Signed-off-by: Sukumar Ghorai <s-ghorai@ti.com>
---
arch/arm/mach-omap2/Makefile | 2 +-
arch/arm/mach-omap2/board-3430sdp.c | 16 +++-
.../{board-sdp-flash.c => board-flash.c} | 88 ++++++++-----------
.../include/mach/{board-sdp.h => board-flash.h} | 9 ++-
4 files changed, 60 insertions(+), 55 deletions(-)
rename arch/arm/mach-omap2/{board-sdp-flash.c => board-flash.c} (68%)
rename arch/arm/mach-omap2/include/mach/{board-sdp.h => board-flash.h} (71%)
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index 6c6d7c6..0d854f1 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -117,7 +117,7 @@ obj-$(CONFIG_MACH_OMAP3_PANDORA) += board-omap3pandora.o \
hsmmc.o
obj-$(CONFIG_MACH_OMAP_3430SDP) += board-3430sdp.o \
hsmmc.o \
- board-sdp-flash.o
+ board-flash.o
obj-$(CONFIG_MACH_NOKIA_N8X0) += board-n8x0.o
obj-$(CONFIG_MACH_NOKIA_RX51) += board-rx51.o \
board-rx51-sdram.o \
diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
index f474a80..4b8595b 100644
--- a/arch/arm/mach-omap2/board-3430sdp.c
+++ b/arch/arm/mach-omap2/board-3430sdp.c
@@ -41,7 +41,7 @@
#include <plat/control.h>
#include <plat/gpmc-smc91x.h>
-#include <mach/board-sdp.h>
+#include <mach/board-flash.h>
#include "mux.h"
#include "sdram-qimonda-hyb18m512160af-6.h"
@@ -667,6 +667,18 @@ static struct omap_board_mux board_mux[] __initdata = {
#define board_mux NULL
#endif
+/*
+ * SDP3430 V2 Board CS organization
+ * Different from SDP3430 V1. Now 4 switches used to specify CS
+ *
+ * See also the Switch S8 settings in the comments.
+ */
+static char chip_sel_3430[][GPMC_CS_NUM] = {
+ {PDC_NOR, PDC_NAND, PDC_ONENAND, DBG_MPDB, 0, 0, 0, 0}, /* S8:1111 */
+ {PDC_ONENAND, PDC_NAND, PDC_NOR, DBG_MPDB, 0, 0, 0, 0}, /* S8:1110 */
+ {PDC_NAND, PDC_ONENAND, PDC_NOR, DBG_MPDB, 0, 0, 0, 0}, /* S8:1101 */
+};
+
static struct mtd_partition sdp_nor_partitions[] = {
/* bootloader (U-Boot, etc) in first sector */
{
@@ -797,7 +809,7 @@ static void __init omap_3430sdp_init(void)
omap_serial_init();
usb_musb_init(&musb_board_data);
board_smc91x_init();
- sdp_flash_init(sdp_flash_partitions);
+ board_flash_init(sdp_flash_partitions, chip_sel_3430);
sdp3430_display_init();
enable_board_wakeup_source();
usb_ehci_init(&ehci_pdata);
diff --git a/arch/arm/mach-omap2/board-sdp-flash.c b/arch/arm/mach-omap2/board-flash.c
similarity index 68%
rename from arch/arm/mach-omap2/board-sdp-flash.c
rename to arch/arm/mach-omap2/board-flash.c
index 2638c83..ac834aa 100755
--- a/arch/arm/mach-omap2/board-sdp-flash.c
+++ b/arch/arm/mach-omap2/board-flash.c
@@ -21,7 +21,7 @@
#include <plat/nand.h>
#include <plat/onenand.h>
#include <plat/tc.h>
-#include <mach/board-sdp.h>
+#include <mach/board-flash.h>
#define REG_FPGA_REV 0x10
#define REG_FPGA_DIP_SWITCH_INPUT2 0x60
@@ -29,72 +29,53 @@
#define DEBUG_BASE 0x08000000 /* debug board */
-#define PDC_NOR 1
-#define PDC_NAND 2
-#define PDC_ONENAND 3
-#define DBG_MPDB 4
-
/* various memory sizes */
#define FLASH_SIZE_SDPV1 SZ_64M /* NOR flash (64 Meg aligned) */
#define FLASH_SIZE_SDPV2 SZ_128M /* NOR flash (256 Meg aligned) */
-/*
- * SDP3430 V2 Board CS organization
- * Different from SDP3430 V1. Now 4 switches used to specify CS
- *
- * See also the Switch S8 settings in the comments.
- *
- * REVISIT: Add support for 2430 SDP
- */
-static const unsigned char chip_sel_sdp[][GPMC_CS_NUM] = {
- {PDC_NOR, PDC_NAND, PDC_ONENAND, DBG_MPDB, 0, 0, 0, 0}, /* S8:1111 */
- {PDC_ONENAND, PDC_NAND, PDC_NOR, DBG_MPDB, 0, 0, 0, 0}, /* S8:1110 */
- {PDC_NAND, PDC_ONENAND, PDC_NOR, DBG_MPDB, 0, 0, 0, 0}, /* S8:1101 */
-};
-
-static struct physmap_flash_data sdp_nor_data = {
+static struct physmap_flash_data board_nor_data = {
.width = 2,
};
-static struct resource sdp_nor_resource = {
+static struct resource board_nor_resource = {
.flags = IORESOURCE_MEM,
};
-static struct platform_device sdp_nor_device = {
+static struct platform_device board_nor_device = {
.name = "physmap-flash",
.id = 0,
.dev = {
- .platform_data = &sdp_nor_data,
+ .platform_data = &board_nor_data,
},
.num_resources = 1,
- .resource = &sdp_nor_resource,
+ .resource = &board_nor_resource,
};
static void
-__init board_nor_init(struct flash_partitions sdp_nor_parts, u8 cs)
+__init board_nor_init(struct mtd_partition *nor_parts, u8 nr_parts, u8 cs)
{
int err;
- sdp_nor_data.parts = sdp_nor_parts.parts;
- sdp_nor_data.nr_parts = sdp_nor_parts.nr_parts;
+ board_nor_data.parts = nor_parts;
+ board_nor_data.nr_parts = nr_parts;
/* Configure start address and size of NOR device */
if (omap_rev() >= OMAP3430_REV_ES1_0) {
err = gpmc_cs_request(cs, FLASH_SIZE_SDPV2 - 1,
- (unsigned long *)&sdp_nor_resource.start);
- sdp_nor_resource.end = sdp_nor_resource.start
+ (unsigned long *)&board_nor_resource.start);
+ board_nor_resource.end = board_nor_resource.start
+ FLASH_SIZE_SDPV2 - 1;
} else {
err = gpmc_cs_request(cs, FLASH_SIZE_SDPV1 - 1,
- (unsigned long *)&sdp_nor_resource.start);
- sdp_nor_resource.end = sdp_nor_resource.start
+ (unsigned long *)&board_nor_resource.start);
+ board_nor_resource.end = board_nor_resource.start
+ FLASH_SIZE_SDPV1 - 1;
}
if (err < 0) {
printk(KERN_ERR "NOR: Can't request GPMC CS\n");
return;
}
- if (platform_device_register(&sdp_nor_device) < 0)
+ if (platform_device_register(&board_nor_device) < 0)
printk(KERN_ERR "Unable to register NOR device\n");
}
@@ -105,17 +86,18 @@ static struct omap_onenand_platform_data board_onenand_data = {
};
static void
-__init board_onenand_init(struct flash_partitions sdp_onenand_parts, u8 cs)
+__init board_onenand_init(struct mtd_partition *onenand_parts,
+ u8 nr_parts, u8 cs)
{
board_onenand_data.cs = cs;
- board_onenand_data.parts = sdp_onenand_parts.parts;
- board_onenand_data.nr_parts = sdp_onenand_parts.nr_parts;
+ board_onenand_data.parts = onenand_parts;
+ board_onenand_data.nr_parts = nr_parts;
gpmc_onenand_init(&board_onenand_data);
}
#else
static void
-__init board_onenand_init(struct flash_partitions sdp_onenand_parts, u8 cs)
+__init board_onenand_init(struct mtd_partition *nor_parts, u8 nr_parts, u8 cs)
{
}
#endif /* CONFIG_MTD_ONENAND_OMAP2 || CONFIG_MTD_ONENAND_OMAP2_MODULE */
@@ -147,7 +129,7 @@ static struct gpmc_timings nand_timings = {
.wr_data_mux_bus = 0,
};
-static struct omap_nand_platform_data sdp_nand_data = {
+static struct omap_nand_platform_data board_nand_data = {
.nand_setup = NULL,
.gpmc_t = &nand_timings,
.dma_channel = -1, /* disable DMA in OMAP NAND driver */
@@ -155,18 +137,18 @@ static struct omap_nand_platform_data sdp_nand_data = {
.devsize = 0, /* '0' for 8-bit, '1' for 16-bit device */
};
-static void
-__init board_nand_init(struct flash_partitions sdp_nand_parts, u8 cs)
+void
+__init board_nand_init(struct mtd_partition *nand_parts, u8 nr_parts, u8 cs)
{
- sdp_nand_data.cs = cs;
- sdp_nand_data.parts = sdp_nand_parts.parts;
- sdp_nand_data.nr_parts = sdp_nand_parts.nr_parts;
+ board_nand_data.cs = cs;
+ board_nand_data.parts = nand_parts;
+ board_nand_data.nr_parts = nr_parts;
- gpmc_nand_init(&sdp_nand_data);
+ gpmc_nand_init(&board_nand_data);
}
#else
-static void
-__init board_nand_init(struct flash_partitions sdp_nand_parts, u8 cs)
+void
+__init board_nand_init(struct mtd_partition *nand_parts, u8 nr_parts, u8 cs)
{
}
#endif /* CONFIG_MTD_NAND_OMAP2 || CONFIG_MTD_NAND_OMAP2_MODULE */
@@ -210,7 +192,8 @@ unmap:
*
* @return - void.
*/
-void __init sdp_flash_init(struct flash_partitions sdp_partition_info[])
+void board_flash_init(struct flash_partitions partition_info[],
+ char chip_sel_board[][GPMC_CS_NUM])
{
u8 cs = 0;
u8 norcs = GPMC_CS_NUM + 1;
@@ -227,7 +210,7 @@ void __init sdp_flash_init(struct flash_partitions sdp_partition_info[])
printk(KERN_ERR "%s: Invalid chip select: %d\n", __func__, cs);
return;
}
- config_sel = (unsigned char *)(chip_sel_sdp[idx]);
+ config_sel = (unsigned char *)(chip_sel_board[idx]);
while (cs < GPMC_CS_NUM) {
switch (config_sel[cs]) {
@@ -251,17 +234,20 @@ void __init sdp_flash_init(struct flash_partitions sdp_partition_info[])
printk(KERN_INFO "NOR: Unable to find configuration "
"in GPMC\n");
else
- board_nor_init(sdp_partition_info[0], norcs);
+ board_nor_init(partition_info[0].parts,
+ partition_info[0].nr_parts, norcs);
if (onenandcs > GPMC_CS_NUM)
printk(KERN_INFO "OneNAND: Unable to find configuration "
"in GPMC\n");
else
- board_onenand_init(sdp_partition_info[1], onenandcs);
+ board_onenand_init(partition_info[1].parts,
+ partition_info[1].nr_parts, onenandcs);
if (nandcs > GPMC_CS_NUM)
printk(KERN_INFO "NAND: Unable to find configuration "
"in GPMC\n");
else
- board_nand_init(sdp_partition_info[2], nandcs);
+ board_nand_init(partition_info[2].parts,
+ partition_info[2].nr_parts, nandcs);
}
diff --git a/arch/arm/mach-omap2/include/mach/board-sdp.h b/arch/arm/mach-omap2/include/mach/board-flash.h
similarity index 71%
rename from arch/arm/mach-omap2/include/mach/board-sdp.h
rename to arch/arm/mach-omap2/include/mach/board-flash.h
index 465169c..b2242ae 100644
--- a/arch/arm/mach-omap2/include/mach/board-sdp.h
+++ b/arch/arm/mach-omap2/include/mach/board-flash.h
@@ -12,10 +12,17 @@
*/
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
+#include <plat/gpmc.h>
+
+#define PDC_NOR 1
+#define PDC_NAND 2
+#define PDC_ONENAND 3
+#define DBG_MPDB 4
struct flash_partitions {
struct mtd_partition *parts;
int nr_parts;
};
-extern void sdp_flash_init(struct flash_partitions []);
+extern void board_flash_init(struct flash_partitions [],
+ char chip_sel[][GPMC_CS_NUM]);
--
1.5.4.7
^ permalink raw reply related [flat|nested] 102+ messages in thread
* Re: [PATCH v5 1/3] omap3 gpmc: functionality enhancement
2010-06-04 7:40 ` [PATCH v5 1/3] omap3 gpmc: functionality enhancement Sukumar Ghorai
2010-06-04 7:40 ` [PATCH v5 2/3] omap3 nand: cleanup virtual address usages Sukumar Ghorai
@ 2010-07-07 10:18 ` Tony Lindgren
2010-07-07 12:32 ` Ghorai, Sukumar
1 sibling, 1 reply; 102+ messages in thread
From: Tony Lindgren @ 2010-07-07 10:18 UTC (permalink / raw)
To: Sukumar Ghorai; +Cc: linux-omap, linux-mtd, mike
* Sukumar Ghorai <s-ghorai@ti.com> [100604 10:34]:
> few functions added in gpmc module and to be used by other drivers like NAND.
> E.g.: - ioctl function
> - ecc functions
Uhh, let's leave out ioctl from the description.. Otherwise people
think you're adding new ioctls in this patch.
> @@ -46,8 +46,9 @@
> #define GPMC_ECC_CONFIG 0x1f4
> #define GPMC_ECC_CONTROL 0x1f8
> #define GPMC_ECC_SIZE_CONFIG 0x1fc
> +#define GPMC_ECC1_RESULT 0x200
>
> -#define GPMC_CS0 0x60
> +#define GPMC_CS0_BASE 0x60
> #define GPMC_CS_SIZE 0x30
>
> #define GPMC_MEM_START 0x00000000
Why changing GPMC_CS0 to GPMC_CS0_BASE? Should it rather be
GPMC_CS0_OFFSET?
> @@ -419,8 +437,100 @@ void gpmc_cs_free(int cs)
> EXPORT_SYMBOL(gpmc_cs_free);
>
> /**
> + * gpmc_hwcontrol - hardware specific access (read/ write) control
> + * @cs: chip select number
> + * @cmd: command type
> + * @write: 1 for write; 0 for read
> + * @wval: value to write
> + * @rval: read pointer
> + */
> +int gpmc_hwcontrol(int cs, int cmd, int write, int wval, int *rval)
> +{
> + u32 regval = 0;
> +
> + if (!write && !rval)
> + return -EINVAL;
You pass int write, then return immediately if it's not set?
> + switch (cmd) {
> + case GPMC_STATUS_BUFFER:
> + regval = gpmc_read_reg(GPMC_STATUS);
> + /* 1 : buffer is available to write */
> + *rval = regval & GPMC_STATUS_BUFF_EMPTY;
> + break;
> +
> + case GPMC_GET_SET_IRQ_STATUS:
> + if (write)
> + gpmc_write_reg(GPMC_IRQSTATUS, wval);
> + else
> + *rval = gpmc_read_reg(GPMC_IRQSTATUS);
> + break;
> +
> + case GPMC_PREFETCH_FIFO_CNT:
> + regval = gpmc_read_reg(GPMC_PREFETCH_STATUS);
> + *rval = GPMC_PREFETCH_STATUS_FIFO_CNT(regval);
> + break;
> +
> + case GPMC_PREFETCH_COUNT:
> + regval = gpmc_read_reg(GPMC_PREFETCH_STATUS);
> + *rval = GPMC_PREFETCH_STATUS_COUNT(regval);
> + break;
> +
> + case GPMC_CONFIG_WP:
> + regval = gpmc_read_reg(GPMC_CONFIG);
> + if (wval)
> + regval &= ~GPMC_CONFIG_WRITEPROTECT; /* WP is ON */
> + else
> + regval |= GPMC_CONFIG_WRITEPROTECT; /* WP is OFF */
> + gpmc_write_reg(GPMC_CONFIG, regval);
> + break;
> +
> + case GPMC_CONFIG_RDY_BSY:
> + regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
> + regval |= WR_RD_PIN_MONITORING;
> + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
> + break;
> +
> + case GPMC_CONFIG_DEV_SIZE:
> + regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
> + regval |= GPMC_CONFIG1_DEVICESIZE(wval);
> + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
> + break;
> +
> + case GPMC_CONFIG_DEV_TYPE:
> + regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
> + regval |= GPMC_CONFIG1_DEVICETYPE(wval);
> + if (wval == GPMC_DEVICETYPE_NOR)
> + regval |= GPMC_CONFIG1_MUXADDDATA;
> + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
> + break;
> +
> + case GPMC_NAND_COMMAND:
> + gpmc_cs_write_byte(cs, GPMC_CS_NAND_COMMAND, wval);
> + break;
> +
> + case GPMC_NAND_ADDRESS:
> + gpmc_cs_write_byte(cs, GPMC_CS_NAND_ADDRESS, wval);
> + break;
> +
> + case GPMC_NAND_DATA:
> + if (write)
> + gpmc_cs_write_byte(cs, GPMC_CS_NAND_DATA, wval);
> + else
> + *rval = gpmc_cs_read_byte(cs, GPMC_CS_NAND_DATA);
> + break;
> +
> + default:
> + printk(KERN_ERR "gpmc_hwcontrol: Not supported\n");
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +EXPORT_SYMBOL(gpmc_hwcontrol);
You should just replace this function with simple functions like we already
have in gpmc.c rather than trying to pack everything into one function.
Just add various gpmc_xxx_get/set functions rather than pass int *rval.
Regards,
Tony
^ permalink raw reply [flat|nested] 102+ messages in thread
* Re: [PATCH v5 2/3] omap3 nand: cleanup virtual address usages
2010-06-04 7:40 ` [PATCH v5 2/3] omap3 nand: cleanup virtual address usages Sukumar Ghorai
2010-06-04 7:40 ` [PATCH v5 3/3] omap3 nand: fix issue in board file to detect nand Sukumar Ghorai
@ 2010-07-07 10:21 ` Tony Lindgren
2010-07-07 12:22 ` Ghorai, Sukumar
1 sibling, 1 reply; 102+ messages in thread
From: Tony Lindgren @ 2010-07-07 10:21 UTC (permalink / raw)
To: Sukumar Ghorai; +Cc: linux-omap, linux-mtd, mike
* Sukumar Ghorai <s-ghorai@ti.com> [100604 10:34]:
> --- a/arch/arm/plat-omap/include/plat/gpmc.h
> +++ b/arch/arm/plat-omap/include/plat/gpmc.h
> @@ -63,7 +60,6 @@
> #define GPMC_CONFIG1_DEVICESIZE_16 GPMC_CONFIG1_DEVICESIZE(1)
> #define GPMC_CONFIG1_DEVICETYPE(val) ((val & 3) << 10)
> #define GPMC_CONFIG1_DEVICETYPE_NOR GPMC_CONFIG1_DEVICETYPE(0)
> -#define GPMC_CONFIG1_DEVICETYPE_NAND GPMC_CONFIG1_DEVICETYPE(2)
> #define GPMC_CONFIG1_MUXADDDATA (1 << 9)
> #define GPMC_CONFIG1_TIME_PARA_GRAN (1 << 4)
> #define GPMC_CONFIG1_FCLK_DIV(val) (val & 3)
Is this no longer needed?
> --- a/arch/arm/plat-omap/include/plat/nand.h
> +++ b/arch/arm/plat-omap/include/plat/nand.h
> @@ -21,13 +21,11 @@ struct omap_nand_platform_data {
> int (*dev_ready)(struct omap_nand_platform_data *);
> int dma_channel;
> unsigned long phys_base;
> - void __iomem *gpmc_cs_baseaddr;
> - void __iomem *gpmc_baseaddr;
> int devsize;
> };
Glad to see these finally going away!
Regards,
Tony
^ permalink raw reply [flat|nested] 102+ messages in thread
* RE: [PATCH v5 2/3] omap3 nand: cleanup virtual address usages
2010-07-07 10:21 ` [PATCH v5 2/3] omap3 nand: cleanup virtual address usages Tony Lindgren
@ 2010-07-07 12:22 ` Ghorai, Sukumar
0 siblings, 0 replies; 102+ messages in thread
From: Ghorai, Sukumar @ 2010-07-07 12:22 UTC (permalink / raw)
To: Tony Lindgren
Cc: linux-omap@vger.kernel.org, linux-mtd@lists.infradead.org,
mike@compulab.co.il
Tony,
> -----Original Message-----
> From: Tony Lindgren [mailto:tony@atomide.com]
> Sent: Wednesday, July 07, 2010 3:52 PM
> To: Ghorai, Sukumar
> Cc: linux-omap@vger.kernel.org; linux-mtd@lists.infradead.org;
> mike@compulab.co.il
> Subject: Re: [PATCH v5 2/3] omap3 nand: cleanup virtual address usages
>
> * Sukumar Ghorai <s-ghorai@ti.com> [100604 10:34]:
> > --- a/arch/arm/plat-omap/include/plat/gpmc.h
> > +++ b/arch/arm/plat-omap/include/plat/gpmc.h
> > @@ -63,7 +60,6 @@
> > #define GPMC_CONFIG1_DEVICESIZE_16 GPMC_CONFIG1_DEVICESIZE(1)
> > #define GPMC_CONFIG1_DEVICETYPE(val) ((val & 3) << 10)
> > #define GPMC_CONFIG1_DEVICETYPE_NOR GPMC_CONFIG1_DEVICETYPE(0)
> > -#define GPMC_CONFIG1_DEVICETYPE_NAND GPMC_CONFIG1_DEVICETYPE(2)
> > #define GPMC_CONFIG1_MUXADDDATA (1 << 9)
> > #define GPMC_CONFIG1_TIME_PARA_GRAN (1 << 4)
> > #define GPMC_CONFIG1_FCLK_DIV(val) (val & 3)
>
> Is this no longer needed?
[Ghorai] we pass GPMC_CONFIG_DEV_TYPE and GPMC_DEVICETYPE_NAND to gpmc_hwcontrol(); And GPMC_DEVICETYPE_NAND define in previous patch of the same series.
>
> > --- a/arch/arm/plat-omap/include/plat/nand.h
> > +++ b/arch/arm/plat-omap/include/plat/nand.h
> > @@ -21,13 +21,11 @@ struct omap_nand_platform_data {
> > int (*dev_ready)(struct omap_nand_platform_data *);
> > int dma_channel;
> > unsigned long phys_base;
> > - void __iomem *gpmc_cs_baseaddr;
> > - void __iomem *gpmc_baseaddr;
> > int devsize;
> > };
>
> Glad to see these finally going away!
>
> Regards,
>
> Tony
^ permalink raw reply [flat|nested] 102+ messages in thread
* RE: [PATCH v5 1/3] omap3 gpmc: functionality enhancement
2010-07-07 10:18 ` [PATCH v5 1/3] omap3 gpmc: functionality enhancement Tony Lindgren
@ 2010-07-07 12:32 ` Ghorai, Sukumar
2010-07-07 13:01 ` Tony Lindgren
0 siblings, 1 reply; 102+ messages in thread
From: Ghorai, Sukumar @ 2010-07-07 12:32 UTC (permalink / raw)
To: Tony Lindgren
Cc: linux-omap@vger.kernel.org, linux-mtd@lists.infradead.org,
mike@compulab.co.il
Tony,
> -----Original Message-----
> From: Tony Lindgren [mailto:tony@atomide.com]
> Sent: Wednesday, July 07, 2010 3:49 PM
> To: Ghorai, Sukumar
> Cc: linux-omap@vger.kernel.org; linux-mtd@lists.infradead.org;
> mike@compulab.co.il
> Subject: Re: [PATCH v5 1/3] omap3 gpmc: functionality enhancement
>
> * Sukumar Ghorai <s-ghorai@ti.com> [100604 10:34]:
> > few functions added in gpmc module and to be used by other drivers like
> NAND.
> > E.g.: - ioctl function
> > - ecc functions
>
> Uhh, let's leave out ioctl from the description.. Otherwise people
> think you're adding new ioctls in this patch.
[Ghorai] I am agree.
>
> > @@ -46,8 +46,9 @@
> > #define GPMC_ECC_CONFIG 0x1f4
> > #define GPMC_ECC_CONTROL 0x1f8
> > #define GPMC_ECC_SIZE_CONFIG 0x1fc
> > +#define GPMC_ECC1_RESULT 0x200
> >
> > -#define GPMC_CS0 0x60
> > +#define GPMC_CS0_BASE 0x60
> > #define GPMC_CS_SIZE 0x30
> >
> > #define GPMC_MEM_START 0x00000000
>
> Why changing GPMC_CS0 to GPMC_CS0_BASE? Should it rather be
> GPMC_CS0_OFFSET?
[Ghorai] I am agree with your input.
>
> > @@ -419,8 +437,100 @@ void gpmc_cs_free(int cs)
> > EXPORT_SYMBOL(gpmc_cs_free);
> >
> > /**
> > + * gpmc_hwcontrol - hardware specific access (read/ write) control
> > + * @cs: chip select number
> > + * @cmd: command type
> > + * @write: 1 for write; 0 for read
> > + * @wval: value to write
> > + * @rval: read pointer
> > + */
> > +int gpmc_hwcontrol(int cs, int cmd, int write, int wval, int *rval)
> > +{
> > + u32 regval = 0;
> > +
> > + if (!write && !rval)
> > + return -EINVAL;
>
> You pass int write, then return immediately if it's not set?
[Ghorai] This is just to check if argument passed correctly either for read or write functionally to do. We can remove this checking.
>
> > + switch (cmd) {
> > + case GPMC_STATUS_BUFFER:
> > + regval = gpmc_read_reg(GPMC_STATUS);
> > + /* 1 : buffer is available to write */
> > + *rval = regval & GPMC_STATUS_BUFF_EMPTY;
> > + break;
> > +
> > + case GPMC_GET_SET_IRQ_STATUS:
> > + if (write)
> > + gpmc_write_reg(GPMC_IRQSTATUS, wval);
> > + else
> > + *rval = gpmc_read_reg(GPMC_IRQSTATUS);
> > + break;
> > +
> > + case GPMC_PREFETCH_FIFO_CNT:
> > + regval = gpmc_read_reg(GPMC_PREFETCH_STATUS);
> > + *rval = GPMC_PREFETCH_STATUS_FIFO_CNT(regval);
> > + break;
> > +
> > + case GPMC_PREFETCH_COUNT:
> > + regval = gpmc_read_reg(GPMC_PREFETCH_STATUS);
> > + *rval = GPMC_PREFETCH_STATUS_COUNT(regval);
> > + break;
> > +
> > + case GPMC_CONFIG_WP:
> > + regval = gpmc_read_reg(GPMC_CONFIG);
> > + if (wval)
> > + regval &= ~GPMC_CONFIG_WRITEPROTECT; /* WP is ON */
> > + else
> > + regval |= GPMC_CONFIG_WRITEPROTECT; /* WP is OFF */
> > + gpmc_write_reg(GPMC_CONFIG, regval);
> > + break;
> > +
> > + case GPMC_CONFIG_RDY_BSY:
> > + regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
> > + regval |= WR_RD_PIN_MONITORING;
> > + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
> > + break;
> > +
> > + case GPMC_CONFIG_DEV_SIZE:
> > + regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
> > + regval |= GPMC_CONFIG1_DEVICESIZE(wval);
> > + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
> > + break;
> > +
> > + case GPMC_CONFIG_DEV_TYPE:
> > + regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
> > + regval |= GPMC_CONFIG1_DEVICETYPE(wval);
> > + if (wval == GPMC_DEVICETYPE_NOR)
> > + regval |= GPMC_CONFIG1_MUXADDDATA;
> > + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
> > + break;
> > +
> > + case GPMC_NAND_COMMAND:
> > + gpmc_cs_write_byte(cs, GPMC_CS_NAND_COMMAND, wval);
> > + break;
> > +
> > + case GPMC_NAND_ADDRESS:
> > + gpmc_cs_write_byte(cs, GPMC_CS_NAND_ADDRESS, wval);
> > + break;
> > +
> > + case GPMC_NAND_DATA:
> > + if (write)
> > + gpmc_cs_write_byte(cs, GPMC_CS_NAND_DATA, wval);
> > + else
> > + *rval = gpmc_cs_read_byte(cs, GPMC_CS_NAND_DATA);
> > + break;
> > +
> > + default:
> > + printk(KERN_ERR "gpmc_hwcontrol: Not supported\n");
> > + return -EINVAL;
> > + }
> > +
> > + return 0;
> > +}
> > +EXPORT_SYMBOL(gpmc_hwcontrol);
>
> You should just replace this function with simple functions like we
> already
> have in gpmc.c rather than trying to pack everything into one function.
> Just add various gpmc_xxx_get/set functions rather than pass int *rval.
[Ghorai] So I was having the same query very 1st time.
So we need to implement 15 separate functions to do the same as you suggested. And in my approach it's very easy to enhance the functionally in future, say to add new set/get. E.g. we need the similar cleanup for OneNAND code too.
So, would you please confirm once again with one is the best and should follow?
>
> Regards,
>
> Tony
^ permalink raw reply [flat|nested] 102+ messages in thread
* Re: [PATCH v5 1/3] omap3 gpmc: functionality enhancement
2010-07-07 12:32 ` Ghorai, Sukumar
@ 2010-07-07 13:01 ` Tony Lindgren
2010-07-08 3:54 ` Ghorai, Sukumar
0 siblings, 1 reply; 102+ messages in thread
From: Tony Lindgren @ 2010-07-07 13:01 UTC (permalink / raw)
To: Ghorai, Sukumar
Cc: linux-omap@vger.kernel.org, linux-mtd@lists.infradead.org,
mike@compulab.co.il
* Ghorai, Sukumar <s-ghorai@ti.com> [100707 15:26]:
> > From: Tony Lindgren [mailto:tony@atomide.com]
> >
> > You should just replace this function with simple functions like we
> > already
> > have in gpmc.c rather than trying to pack everything into one function.
> > Just add various gpmc_xxx_get/set functions rather than pass int *rval.
>
> [Ghorai] So I was having the same query very 1st time.
> So we need to implement 15 separate functions to do the same as you suggested. And in my approach it's very easy to enhance the functionally in future, say to add new set/get. E.g. we need the similar cleanup for OneNAND code too.
> So, would you please confirm once again with one is the best and should follow?
In general, we should have separate read and write functions.
Maybe you can group them a little bit? Some of them need the chip
select, and some of them are generic. Then some of them are NAND
specific.
Regards,
Tony
^ permalink raw reply [flat|nested] 102+ messages in thread
* RE: [PATCH v5 1/3] omap3 gpmc: functionality enhancement
2010-07-07 13:01 ` Tony Lindgren
@ 2010-07-08 3:54 ` Ghorai, Sukumar
0 siblings, 0 replies; 102+ messages in thread
From: Ghorai, Sukumar @ 2010-07-08 3:54 UTC (permalink / raw)
To: Tony Lindgren
Cc: linux-omap@vger.kernel.org, linux-mtd@lists.infradead.org,
mike@compulab.co.il
> -----Original Message-----
> From: Tony Lindgren [mailto:tony@atomide.com]
> Sent: Wednesday, July 07, 2010 6:32 PM
> To: Ghorai, Sukumar
> Cc: linux-omap@vger.kernel.org; linux-mtd@lists.infradead.org;
> mike@compulab.co.il
> Subject: Re: [PATCH v5 1/3] omap3 gpmc: functionality enhancement
>
> * Ghorai, Sukumar <s-ghorai@ti.com> [100707 15:26]:
> > > From: Tony Lindgren [mailto:tony@atomide.com]
> > >
> > > You should just replace this function with simple functions like we
> > > already
> > > have in gpmc.c rather than trying to pack everything into one function.
> > > Just add various gpmc_xxx_get/set functions rather than pass int *rval.
> >
> > [Ghorai] So I was having the same query very 1st time.
> > So we need to implement 15 separate functions to do the same as you
> suggested. And in my approach it's very easy to enhance the functionally
> in future, say to add new set/get. E.g. we need the similar cleanup for
> OneNAND code too.
> > So, would you please confirm once again with one is the best and should
> follow?
>
> In general, we should have separate read and write functions.
>
> Maybe you can group them a little bit? Some of them need the chip
> select, and some of them are generic. Then some of them are NAND
> specific.
[Ghorai] ok. And let me re-work this for next version.
>
> Regards,
>
> Tony
^ permalink raw reply [flat|nested] 102+ messages in thread
end of thread, other threads:[~2010-07-08 3:54 UTC | newest]
Thread overview: 102+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <Sukumar Ghorai <s-ghorai@ti.com>
2010-04-06 12:29 ` [PATCH 0/2] OMAP: Flash device support 3630 sdp board Sukumar Ghorai
2010-04-06 12:29 ` [PATCH 1/2] OMAP3630SDP: Add support for Flash Sukumar Ghorai
2010-04-06 12:29 ` [PATCH 2/2] OMAP3630SDP: enable Flash device support Sukumar Ghorai
2010-04-06 13:02 ` [PATCH 1/2] OMAP3630SDP: Add support for Flash Vimal Singh
2010-04-13 17:37 ` [PATCH] nand support on omap3 boards Sukumar Ghorai
2010-04-13 17:37 ` [PATCH v3 1/8] omap3: zoom: Introducing 'board-zoom-flash.c' Sukumar Ghorai
2010-04-13 17:37 ` [PATCH v3 2/8] omap3: add support for NAND on zoom2 board Sukumar Ghorai
2010-04-13 17:37 ` [PATCH v3 3/8] omap3: add support for NAND on zoom3 board Sukumar Ghorai
2010-04-13 17:37 ` [PATCH v2 4/8] omap-3630-sdp : Add support for Flash Sukumar Ghorai
2010-04-13 17:37 ` [PATCH v2 5/8] omap-3630-sdp: enable Flash device support Sukumar Ghorai
2010-04-13 17:37 ` [PATCH v2 6/8] omap3: add support for NAND on LDP board Sukumar Ghorai
2010-04-13 17:37 ` [PATCH 7/8] zoom2: enable NAND support Sukumar Ghorai
2010-04-13 17:37 ` [PATCH 8/8] zoom3: " Sukumar Ghorai
2010-04-13 17:37 ` [PATCH] nand support on omap3 boards Sukumar Ghorai
2010-04-13 17:37 ` [PATCH 8/8] omap3: GPMC register definition at common location Sukumar Ghorai
2010-04-13 17:37 ` [PATCH] omap3: NAND Prefetch in IRQ mode support Sukumar Ghorai
2010-04-13 17:37 ` [PATCH] omap-3630 NAND: enable NAND io in prefetch-irq mode Sukumar Ghorai
2010-04-13 17:37 ` [PATCH] omap: NAND: ecc layout select from board file Sukumar Ghorai
2010-04-13 17:37 ` [PATCH] omap: NAND: Making ecc layout as compatible with romcode ecc Sukumar Ghorai
2010-04-14 4:35 ` [PATCH] nand support on omap3 boards Vimal Singh
2010-04-14 4:37 ` Vimal Singh
2010-04-14 4:38 ` Ghorai, Sukumar
2010-05-04 6:00 ` Ghorai, Sukumar
2010-05-04 6:01 ` Ghorai, Sukumar
2010-05-28 13:48 ` Ghorai, Sukumar
2010-04-13 17:44 ` Sukumar Ghorai
2010-04-16 11:32 ` [PATCH 0/6] nand prefetch-irq support and ecc layout chanage Sukumar Ghorai
2010-04-16 11:34 ` [PATCH 1/6] omap3: GPMC register definition at common location Sukumar Ghorai
2010-04-16 11:35 ` [PATCH 2/6] omap3: NAND Prefetch in IRQ mode support Sukumar Ghorai
2010-04-16 11:35 ` [PATCH 3/6] OMAP NAND: configurable fifo threshold to gain the throughput Sukumar Ghorai
2010-04-16 12:45 ` Vimal Singh
2010-04-16 11:35 ` [PATCH 4/6] omap-3630 NAND: enable NAND io in prefetch-irq mode Sukumar Ghorai
2010-04-16 11:35 ` [PATCH 5/6] omap: NAND: ecc layout select from board file Sukumar Ghorai
2010-04-16 11:35 ` [PATCH 6/6] omap: NAND: Making ecc layout as compatible with romcode ecc Sukumar Ghorai
2010-05-12 9:48 ` [PATCH 0/3] omap3 nand: cleanup exiting platform related code Sukumar Ghorai
2010-05-12 9:48 ` [PATCH 1/3] omap3: GPMC register definition at common location Sukumar Ghorai
2010-05-12 9:48 ` [PATCH 2/3] omap3 nand: cleanup for not to use GPMC virtual address Sukumar Ghorai
2010-05-12 9:48 ` [PATCH 3/3] omap3 nand: fix issue in board file to detect the nand Sukumar Ghorai
2010-05-13 15:41 ` [PATCH 2/3] omap3 nand: cleanup for not to use GPMC virtual address Tony Lindgren
2010-05-13 18:48 ` Ghorai, Sukumar
2010-05-13 6:15 ` [PATCH 1/3] omap3: GPMC register definition at common location Mike Rapoport
2010-05-13 15:41 ` Tony Lindgren
2010-05-13 15:44 ` [PATCH 0/3] omap3 nand: cleanup exiting platform related code Tony Lindgren
2010-05-14 15:23 ` [PATCH v2 0/2] " Sukumar Ghorai
2010-05-14 15:23 ` [PATCH v2 1/2] omap3 nand: cleanup for not to use GPMC virtual address Sukumar Ghorai
2010-05-14 15:23 ` [PATCH v2 2/2] omap3 nand: fix issue in board file to detect the nand Sukumar Ghorai
2010-05-14 15:28 ` [PATCH v2 1/2] omap3 nand: cleanup for not to use GPMC virtual address Tony Lindgren
2010-05-14 18:02 ` Vimal Singh
2010-05-17 4:22 ` Ghorai, Sukumar
2010-05-17 14:26 ` Vimal Singh
2010-05-17 14:34 ` Ghorai, Sukumar
2010-05-14 23:58 ` Tony Lindgren
2010-05-17 5:48 ` Ghorai, Sukumar
2010-05-18 11:16 ` [PATCH v3 0/3] omap3 nand: cleanup exiting platform related code Sukumar Ghorai
2010-05-18 11:16 ` [PATCH v3 1/3] omap3 gpmc: functionality enhancement Sukumar Ghorai
2010-05-18 11:16 ` [PATCH v3 2/3] omap3 nand: cleanup virtual address usages Sukumar Ghorai
2010-05-18 11:16 ` [PATCH v3 3/3] omap3 nand: fix issue in board file to detect nand Sukumar Ghorai
2010-05-19 15:30 ` [PATCH v3 2/3] omap3 nand: cleanup virtual address usages Vimal Singh
2010-05-19 17:24 ` Ghorai, Sukumar
2010-05-19 18:07 ` Vimal Singh
2010-05-19 18:19 ` Tony Lindgren
2010-05-19 14:46 ` [PATCH v3 1/3] omap3 gpmc: functionality enhancement Vimal Singh
2010-05-19 15:14 ` Peter Barada
2010-05-19 15:48 ` Peter Barada
2010-05-19 18:04 ` Ghorai, Sukumar
2010-05-19 18:30 ` Vimal Singh
2010-05-20 5:38 ` Ghorai, Sukumar
2010-05-20 14:34 ` Vimal Singh
2010-05-25 14:37 ` Ghorai, Sukumar
2010-05-25 15:34 ` Vimal Singh
2010-05-27 13:24 ` [PATCH v4 0/3] omap3 nand: cleanup exiting platform related code Sukumar Ghorai
2010-05-27 13:24 ` [PATCH v4 1/3] omap3 gpmc: functionality enhancement Sukumar Ghorai
2010-05-27 13:24 ` [PATCH v4 2/3] omap3 nand: cleanup virtual address usages Sukumar Ghorai
2010-05-27 13:24 ` [PATCH v4 3/3] omap3 nand: fix issue in board file to detect nand Sukumar Ghorai
2010-05-27 18:26 ` [PATCH v4 1/3] omap3 gpmc: functionality enhancement Vimal Singh
2010-06-04 7:40 ` [PATCH v5 0/3] omap3 nand: cleanup exiting platform related code Sukumar Ghorai
2010-06-04 7:40 ` [PATCH v5 1/3] omap3 gpmc: functionality enhancement Sukumar Ghorai
2010-06-04 7:40 ` [PATCH v5 2/3] omap3 nand: cleanup virtual address usages Sukumar Ghorai
2010-06-04 7:40 ` [PATCH v5 3/3] omap3 nand: fix issue in board file to detect nand Sukumar Ghorai
2010-07-07 10:21 ` [PATCH v5 2/3] omap3 nand: cleanup virtual address usages Tony Lindgren
2010-07-07 12:22 ` Ghorai, Sukumar
2010-07-07 10:18 ` [PATCH v5 1/3] omap3 gpmc: functionality enhancement Tony Lindgren
2010-07-07 12:32 ` Ghorai, Sukumar
2010-07-07 13:01 ` Tony Lindgren
2010-07-08 3:54 ` Ghorai, Sukumar
2010-06-08 17:12 ` [PATCH v5 0/3] omap3 nand: cleanup exiting platform related code Vimal Singh
2010-06-15 13:26 ` Ghorai, Sukumar
2010-06-30 14:42 ` Ghorai, Sukumar
2010-06-16 11:39 ` [PATCH v3 0/8] nand support on omap3 boards Sukumar Ghorai
2010-06-16 11:39 ` [PATCH v3 1/8] omap3 flash: rename board-sdp-flash.c to be use by other boards Sukumar Ghorai
2010-06-16 11:39 ` [PATCH v3 2/8] omap3: add support for NAND on zoom2 board Sukumar Ghorai
2010-06-16 11:39 ` [PATCH v3 3/8] omap3: add support for NAND on zoom3 board Sukumar Ghorai
2010-06-16 11:39 ` [PATCH v3 4/8] omap-3630-sdp : Add support for Flash Sukumar Ghorai
2010-06-16 11:39 ` [PATCH v3 5/8] omap3: add support for NAND on LDP board Sukumar Ghorai
2010-06-16 11:39 ` [PATCH v3 6/8] omap-3630-sdp: enable Flash device support Sukumar Ghorai
2010-06-16 11:39 ` [PATCH v3 7/8] zoom2: enable NAND support Sukumar Ghorai
2010-06-16 11:40 ` [PATCH v3 8/8] zoom3: " Sukumar Ghorai
2010-07-05 12:27 ` [PATCH v3 6/8] omap-3630-sdp: enable Flash device support Tony Lindgren
2010-07-06 5:23 ` Ghorai, Sukumar
2010-07-05 12:23 ` [PATCH v3 1/8] omap3 flash: rename board-sdp-flash.c to be use by other boards Tony Lindgren
2010-07-06 6:05 ` Shilimkar, Santosh
2010-07-06 6:27 ` Ghorai, Sukumar
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).