diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-12 11:45:16 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-12 11:45:16 -0800 |
commit | 8287361abca36504da813638310d2547469283eb (patch) | |
tree | 8d98e9a910885efdb09ae5390a3ae44040557e2f /arch/arm/mach-omap2/gpmc-nand.c | |
parent | 2989950cea13711f0cc573c26cde8fe08a36be03 (diff) | |
parent | 8556650dd3370a927217f16444aac5cc0c71e61b (diff) | |
download | linux-next-8287361abca36504da813638310d2547469283eb.tar.gz |
Merge tag 'headers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC Header cleanups from Olof Johansson:
"This is a collection of header file cleanups, mostly for OMAP and
AT91, that keeps moving the platforms in the direction of
multiplatform by removing the need for mach-dependent header files
used in drivers and other places."
Fix up mostly trivial conflicts as per Olof.
* tag 'headers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (106 commits)
ARM: OMAP2+: Move iommu/iovmm headers to platform_data
ARM: OMAP2+: Make some definitions local
ARM: OMAP2+: Move iommu2 to drivers/iommu/omap-iommu2.c
ARM: OMAP2+: Move plat/iovmm.h to include/linux/omap-iommu.h
ARM: OMAP2+: Move iopgtable header to drivers/iommu/
ARM: OMAP: Merge iommu2.h into iommu.h
atmel: move ATMEL_MAX_UART to platform_data/atmel.h
ARM: OMAP: Remove omap_init_consistent_dma_size()
arm: at91: move at91rm9200 rtc header in drivers/rtc
arm: at91: move reset controller header to arm/arm/mach-at91
arm: at91: move pit define to the driver
arm: at91: move at91_shdwc.h to arch/arm/mach-at91
arm: at91: move board header to arch/arm/mach-at91
arn: at91: move at91_tc.h to arch/arm/mach-at91
arm: at91 move at91_aic.h to arch/arm/mach-at91
arm: at91 move board.h to arch/arm/mach-at91
arm: at91: move platfarm_data to include/linux/platform_data/atmel.h
arm: at91: drop machine defconfig
ARM: OMAP: Remove NEED_MACH_GPIO_H
ARM: OMAP: Remove unnecessary mach and plat includes
...
Diffstat (limited to 'arch/arm/mach-omap2/gpmc-nand.c')
-rw-r--r-- | arch/arm/mach-omap2/gpmc-nand.c | 85 |
1 files changed, 55 insertions, 30 deletions
diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c index 4acf497faeb3..8607735b3ab3 100644 --- a/arch/arm/mach-omap2/gpmc-nand.c +++ b/arch/arm/mach-omap2/gpmc-nand.c @@ -17,9 +17,12 @@ #include <asm/mach/flash.h> -#include <plat/gpmc.h> - +#include "gpmc.h" #include "soc.h" +#include "gpmc-nand.h" + +/* minimum size for IO mapping */ +#define NAND_IO_SIZE 4 static struct resource gpmc_nand_resource[] = { { @@ -40,41 +43,36 @@ static struct platform_device gpmc_nand_device = { .resource = gpmc_nand_resource, }; -static int omap2_nand_gpmc_retime(struct omap_nand_platform_data *gpmc_nand_data) +static int omap2_nand_gpmc_retime( + struct omap_nand_platform_data *gpmc_nand_data, + struct gpmc_timings *gpmc_t) { struct gpmc_timings t; int err; - if (!gpmc_nand_data->gpmc_t) - return 0; - memset(&t, 0, sizeof(t)); - t.sync_clk = gpmc_nand_data->gpmc_t->sync_clk; - t.cs_on = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->cs_on); - t.adv_on = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->adv_on); + t.sync_clk = gpmc_t->sync_clk; + t.cs_on = gpmc_round_ns_to_ticks(gpmc_t->cs_on); + t.adv_on = gpmc_round_ns_to_ticks(gpmc_t->adv_on); /* Read */ - t.adv_rd_off = gpmc_round_ns_to_ticks( - gpmc_nand_data->gpmc_t->adv_rd_off); + t.adv_rd_off = gpmc_round_ns_to_ticks(gpmc_t->adv_rd_off); t.oe_on = t.adv_on; - t.access = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->access); - t.oe_off = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->oe_off); - t.cs_rd_off = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->cs_rd_off); - t.rd_cycle = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->rd_cycle); + t.access = gpmc_round_ns_to_ticks(gpmc_t->access); + t.oe_off = gpmc_round_ns_to_ticks(gpmc_t->oe_off); + t.cs_rd_off = gpmc_round_ns_to_ticks(gpmc_t->cs_rd_off); + t.rd_cycle = gpmc_round_ns_to_ticks(gpmc_t->rd_cycle); /* Write */ - t.adv_wr_off = gpmc_round_ns_to_ticks( - gpmc_nand_data->gpmc_t->adv_wr_off); + t.adv_wr_off = gpmc_round_ns_to_ticks(gpmc_t->adv_wr_off); t.we_on = t.oe_on; if (cpu_is_omap34xx()) { - t.wr_data_mux_bus = gpmc_round_ns_to_ticks( - gpmc_nand_data->gpmc_t->wr_data_mux_bus); - t.wr_access = gpmc_round_ns_to_ticks( - gpmc_nand_data->gpmc_t->wr_access); + t.wr_data_mux_bus = gpmc_round_ns_to_ticks(gpmc_t->wr_data_mux_bus); + t.wr_access = gpmc_round_ns_to_ticks(gpmc_t->wr_access); } - t.we_off = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->we_off); - t.cs_wr_off = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->cs_wr_off); - t.wr_cycle = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->wr_cycle); + t.we_off = gpmc_round_ns_to_ticks(gpmc_t->we_off); + t.cs_wr_off = gpmc_round_ns_to_ticks(gpmc_t->cs_wr_off); + t.wr_cycle = gpmc_round_ns_to_ticks(gpmc_t->wr_cycle); /* Configure GPMC */ if (gpmc_nand_data->devsize == NAND_BUSWIDTH_16) @@ -91,7 +89,29 @@ static int omap2_nand_gpmc_retime(struct omap_nand_platform_data *gpmc_nand_data return 0; } -int __init gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data) +static bool __init gpmc_hwecc_bch_capable(enum omap_ecc ecc_opt) +{ + /* support only OMAP3 class */ + if (!cpu_is_omap34xx()) { + pr_err("BCH ecc is not supported on this CPU\n"); + return 0; + } + + /* + * For now, assume 4-bit mode is only supported on OMAP3630 ES1.x, x>=1. + * Other chips may be added if confirmed to work. + */ + if ((ecc_opt == OMAP_ECC_BCH4_CODE_HW) && + (!cpu_is_omap3630() || (GET_OMAP_REVISION() == 0))) { + pr_err("BCH 4-bit mode is not supported on this CPU\n"); + return 0; + } + + return 1; +} + +int __init gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data, + struct gpmc_timings *gpmc_t) { int err = 0; struct device *dev = &gpmc_nand_device.dev; @@ -112,11 +132,13 @@ int __init gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data) gpmc_get_client_irq(GPMC_IRQ_FIFOEVENTENABLE); gpmc_nand_resource[2].start = gpmc_get_client_irq(GPMC_IRQ_COUNT_EVENT); - /* Set timings in GPMC */ - err = omap2_nand_gpmc_retime(gpmc_nand_data); - if (err < 0) { - dev_err(dev, "Unable to set gpmc timings: %d\n", err); - return err; + + if (gpmc_t) { + err = omap2_nand_gpmc_retime(gpmc_nand_data, gpmc_t); + if (err < 0) { + dev_err(dev, "Unable to set gpmc timings: %d\n", err); + return err; + } } /* Enable RD PIN Monitoring Reg */ @@ -126,6 +148,9 @@ int __init gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data) gpmc_update_nand_reg(&gpmc_nand_data->reg, gpmc_nand_data->cs); + if (!gpmc_hwecc_bch_capable(gpmc_nand_data->ecc_opt)) + return -EINVAL; + err = platform_device_register(&gpmc_nand_device); if (err < 0) { dev_err(dev, "Unable to register NAND device\n"); |