lkml.org 
[lkml]   [2007]   [Apr]   [4]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 73/90] ARM: OMAP: Add onennand board specific support for N800
    Date
    From: Jarkko Lavinen <jarkko.lavinen@nokia.com>

    Add onennand board specific support for N800

    Signed-off-by: Jarkko Lavinen <jarkko.lavinen@nokia.com>
    Signed-off-by: Tony Lindgren <tony@atomide.com>
    ---
    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 <linux/kernel.h>
    #include <linux/platform_device.h>
    #include <asm/mach/flash.h>
    +#include <linux/mtd/onenand_regs.h>
    +
    +#include <asm/io.h>
    #include <asm/arch/onenand.h>
    #include <asm/arch/board.h>
    +#include <asm/arch/gpmc.h>

    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
    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

    \
     
     \ /
      Last update: 2007-04-04 20:19    [from the cache]
    ©2003-2011 Jasper Spaans. Advertise on this site