| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106 | /* * linux/arch/arm/mach-omap2/gpmc-onenand.c * * Copyright (C) 2006 - 2009 Nokia Corporation * Contacts:	Juha Yrjola *		Tony Lindgren * * 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/string.h>#include <linux/kernel.h>#include <linux/platform_device.h>#include <linux/mtd/onenand_regs.h>#include <linux/io.h>#include <linux/platform_data/mtd-onenand-omap2.h>#include <linux/err.h>#include <asm/mach/flash.h>#include "gpmc.h"#include "soc.h"#include "gpmc-onenand.h"#define	ONENAND_IO_SIZE	SZ_128K#define	ONENAND_FLAG_SYNCREAD	(1 << 0)#define	ONENAND_FLAG_SYNCWRITE	(1 << 1)#define	ONENAND_FLAG_HF		(1 << 2)#define	ONENAND_FLAG_VHF	(1 << 3)static unsigned onenand_flags;static unsigned latency;static struct omap_onenand_platform_data *gpmc_onenand_data;static struct resource gpmc_onenand_resource = {	.flags		= IORESOURCE_MEM,};static struct platform_device gpmc_onenand_device = {	.name		= "omap2-onenand",	.id		= -1,	.num_resources	= 1,	.resource	= &gpmc_onenand_resource,};static struct gpmc_timings omap2_onenand_calc_async_timings(void){	struct gpmc_device_timings dev_t;	struct gpmc_timings t;	const int t_cer = 15;	const int t_avdp = 12;	const int t_aavdh = 7;	const int t_ce = 76;	const int t_aa = 76;	const int t_oe = 20;	const int t_cez = 20; /* max of t_cez, t_oez */	const int t_wpl = 40;	const int t_wph = 30;	memset(&dev_t, 0, sizeof(dev_t));	dev_t.mux = true;	dev_t.t_avdp_r = max_t(int, t_avdp, t_cer) * 1000;	dev_t.t_avdp_w = dev_t.t_avdp_r;	dev_t.t_aavdh = t_aavdh * 1000;	dev_t.t_aa = t_aa * 1000;	dev_t.t_ce = t_ce * 1000;	dev_t.t_oe = t_oe * 1000;	dev_t.t_cez_r = t_cez * 1000;	dev_t.t_cez_w = dev_t.t_cez_r;	dev_t.t_wpl = t_wpl * 1000;	dev_t.t_wph = t_wph * 1000;	gpmc_calc_timings(&t, &dev_t);	return t;}static int gpmc_set_async_mode(int cs, struct gpmc_timings *t){	/* Configure GPMC for asynchronous read */	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1,			  GPMC_CONFIG1_DEVICESIZE_16 |			  GPMC_CONFIG1_MUXADDDATA);	return gpmc_cs_set_timings(cs, t);}static void omap2_onenand_set_async_mode(void __iomem *onenand_base){	u32 reg;	/* Ensure sync read and sync write are disabled */	reg = readw(onenand_base + ONENAND_REG_SYS_CFG1);	reg &= ~ONENAND_SYS_CFG1_SYNC_READ & ~ONENAND_SYS_CFG1_SYNC_WRITE;	writew(reg, onenand_base + ONENAND_REG_SYS_CFG1);}static void set_onenand_cfg(void __iomem *onenand_base){	u32 reg;
 |