>From 32aa2b4f6228af777bd36c5f51f7c1288568a474 Mon Sep 17 00:00:00 2001 From: Jarkko Lavinen Date: Wed, 7 Mar 2007 03:11:16 -0800 Subject: [PATCH 73/90] ARM: OMAP: Add onennand board specific support for N800 Add onennand board specific support for N800 Signed-off-by: Jarkko Lavinen Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/board-n800-flash.c | 97 +++++++++++++++++++++++++++++++- include/asm-arm/arch-omap/onenand.h | 1 + 2 files changed, 97 insertions(+), 1 deletions(-) diff --git a/arch/arm/mach-omap2/board-n800-flash.c b/arch/arm/mach-omap2/board-n800-flash.c index cd302ab..4005cfb 100644 --- a/arch/arm/mach-omap2/board-n800-flash.c +++ b/arch/arm/mach-omap2/board-n800-flash.c @@ -12,16 +12,23 @@ #include #include #include +#include + +#include #include #include +#include static struct mtd_partition n800_partitions[8]; +static int n800_onenand_setup(void __iomem *); + static struct omap_onenand_platform_data n800_onenand_data = { .cs = 0, .gpio_irq = 26, .parts = n800_partitions, - .nr_parts = 0 /* filled later */ + .nr_parts = 0, /* filled later */ + .onenand_setup = n800_onenand_setup, }; static struct platform_device n800_onenand_device = { @@ -32,6 +39,94 @@ static struct platform_device n800_onenand_device = { }, }; +static unsigned short omap2_onenand_readw(void __iomem *addr) +{ + return readw(addr); +} + +static void omap2_onenand_writew(unsigned short value, void __iomem *addr) +{ + writew(value, addr); +} + +static int omap2_onenand_set_sync_mode(int cs, void __iomem *onenand_base) +{ + const int min_gpmc_clk_period = 18; + struct gpmc_timings t; + int tick_ns, div, fclk_offset_ns, fclk_offset, gpmc_clk_ns, latency; + u32 reg; + + tick_ns = gpmc_round_ns_to_ticks(1); + div = gpmc_cs_calc_divider(cs, min_gpmc_clk_period); + gpmc_clk_ns = div * tick_ns; + if (gpmc_clk_ns >= 24) + latency = 3; + else + latency = 4; + + /* Configure OneNAND for sync read */ + reg = omap2_onenand_readw(onenand_base + ONENAND_REG_SYS_CFG1); + reg &= ~((0x7 << ONENAND_SYS_CFG1_BRL_SHIFT) | (0x7 << 9)); + reg |= (latency << ONENAND_SYS_CFG1_BRL_SHIFT) | + ONENAND_SYS_CFG1_SYNC_READ | + ONENAND_SYS_CFG1_BL_16; + omap2_onenand_writew(reg, onenand_base + ONENAND_REG_SYS_CFG1); + + /* FIXME: Get timings from platform data */ + /* Set syncronous read timings */ + memset(&t, 0, sizeof(t)); + t.sync_clk = min_gpmc_clk_period; + t.cs_on = 0; + t.adv_on = gpmc_round_ns_to_ticks(7); + fclk_offset_ns = t.adv_on + gpmc_round_ns_to_ticks(7); + fclk_offset = fclk_offset_ns / gpmc_round_ns_to_ticks(1); + t.page_burst_access = gpmc_clk_ns; + + /* Read */ + t.adv_rd_off = fclk_offset_ns + gpmc_round_ns_to_ticks(7); + t.oe_on = t.adv_rd_off; + t.access = fclk_offset_ns + (latency + 1) * gpmc_clk_ns; + t.oe_off = t.access + gpmc_round_ns_to_ticks(1); + t.cs_rd_off = t.oe_off; + t.rd_cycle = t.cs_rd_off + gpmc_round_ns_to_ticks(17); + + /* Write */ + t.adv_wr_off = t.adv_on + gpmc_round_ns_to_ticks(12); + t.we_on = t.adv_wr_off + gpmc_round_ns_to_ticks(1); + t.we_off = t.we_on + gpmc_round_ns_to_ticks(40); + t.cs_wr_off = t.we_off + gpmc_round_ns_to_ticks(1); + t.wr_cycle = t.cs_wr_off + gpmc_round_ns_to_ticks(1); + + /* Configure GPMC for synchronous read */ + fclk_offset %= div; + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, + GPMC_CONFIG1_WRAPBURST_SUPP | + GPMC_CONFIG1_READMULTIPLE_SUPP | + GPMC_CONFIG1_READTYPE_SYNC | + GPMC_CONFIG1_CLKACTIVATIONTIME(fclk_offset) | + GPMC_CONFIG1_PAGE_LEN(2) | + GPMC_CONFIG1_WAIT_READ_MON | + GPMC_CONFIG1_WAIT_PIN_SEL(0) | + GPMC_CONFIG1_DEVICESIZE_16 | + GPMC_CONFIG1_DEVICETYPE_NOR | + GPMC_CONFIG1_MUXADDDATA); + + return gpmc_cs_set_timings(cs, &t); +} + +static int n800_onenand_setup(void __iomem *onenand_base) +{ + struct omap_onenand_platform_data *datap = &n800_onenand_data; + struct device *dev = &n800_onenand_device.dev; + + /* Set sync timings in GPMC */ + if (omap2_onenand_set_sync_mode(datap->cs, onenand_base) < 0) { + dev_err(dev, "Unable to set synchronous mode\n"); + return -EINVAL; + } + + return 0; +} void __init n800_flash_init(void) { diff --git a/include/asm-arm/arch-omap/onenand.h b/include/asm-arm/arch-omap/onenand.h index b8a19be..3e8ab2f 100644 --- a/include/asm-arm/arch-omap/onenand.h +++ b/include/asm-arm/arch-omap/onenand.h @@ -16,4 +16,5 @@ struct omap_onenand_platform_data { int gpio_irq; struct mtd_partition *parts; int nr_parts; + int (*onenand_setup)(void __iomem *); }; -- 1.4.4.2