diff options
Diffstat (limited to 'drivers/mtd')
| -rw-r--r-- | drivers/mtd/nand/Kconfig | 17 | ||||
| -rw-r--r-- | drivers/mtd/nand/omap2.c | 365 | ||||
| -rw-r--r-- | drivers/mtd/nand/r852.c | 2 | ||||
| -rw-r--r-- | drivers/mtd/onenand/omap2.c | 36 | ||||
| -rw-r--r-- | drivers/mtd/sm_ftl.c | 2 | 
5 files changed, 288 insertions, 134 deletions
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index c89592239bc..178e2006063 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -106,23 +106,6 @@ config MTD_NAND_OMAP2  	help            Support for NAND flash on Texas Instruments OMAP2 and OMAP3 platforms. -config MTD_NAND_OMAP_PREFETCH -	bool "GPMC prefetch support for NAND Flash device" -	depends on MTD_NAND_OMAP2 -	default y -	help -	 The NAND device can be accessed for Read/Write using GPMC PREFETCH engine -	 to improve the performance. - -config MTD_NAND_OMAP_PREFETCH_DMA -	depends on MTD_NAND_OMAP_PREFETCH -	bool "DMA mode" -	default n -	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 -  config MTD_NAND_IDS  	tristate diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index 15682ec8530..4e33972ad17 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> @@ -24,6 +25,7 @@  #include <plat/nand.h>  #define	DRIVER_NAME	"omap2-nand" +#define	OMAP_NAND_TIMEOUT_MS	5000  #define NAND_Ecc_P1e		(1 << 0)  #define NAND_Ecc_P2e		(1 << 1) @@ -96,26 +98,19 @@  static const char *part_probes[] = { "cmdlinepart", NULL };  #endif -#ifdef CONFIG_MTD_NAND_OMAP_PREFETCH -static int use_prefetch = 1; - -/* "modprobe ... use_prefetch=0" etc */ -module_param(use_prefetch, bool, 0); -MODULE_PARM_DESC(use_prefetch, "enable/disable use of PREFETCH"); - -#ifdef CONFIG_MTD_NAND_OMAP_PREFETCH_DMA -static int use_dma = 1; +/* oob info generated runtime depending on ecc algorithm and layout selected */ +static struct nand_ecclayout omap_oobinfo; +/* 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, +}; -/* "modprobe ... use_dma=0" etc */ -module_param(use_dma, bool, 0); -MODULE_PARM_DESC(use_dma, "enable/disable use of DMA"); -#else -static const int use_dma; -#endif -#else -const int use_prefetch; -static const int use_dma; -#endif  struct omap_nand_info {  	struct nand_hw_control		controller; @@ -129,6 +124,13 @@ struct omap_nand_info {  	unsigned long			phys_base;  	struct completion		comp;  	int				dma_ch; +	int				gpmc_irq; +	enum { +		OMAP_NAND_IO_READ = 0,	/* read */ +		OMAP_NAND_IO_WRITE,	/* write */ +	} iomode; +	u_char				*buf; +	int					buf_len;  };  /** @@ -256,7 +258,8 @@ 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, +			PREFETCH_FIFOTHRESHOLD_MAX, 0x0, len, 0x0);  	if (ret) {  		/* PFPW engine is busy, use cpu copy method */  		if (info->nand.options & NAND_BUSWIDTH_16) @@ -288,9 +291,10 @@ 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 pref_count = 0, w_count = 0; +	uint32_t w_count = 0;  	int i = 0, ret = 0;  	u16 *p; +	unsigned long tim, limit;  	/* take care of subpage writes */  	if (len % 2 != 0) { @@ -300,7 +304,8 @@ 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, +			PREFETCH_FIFOTHRESHOLD_MAX, 0x0, len, 0x1);  	if (ret) {  		/* PFPW engine is busy, use cpu copy method */  		if (info->nand.options & NAND_BUSWIDTH_16) @@ -316,15 +321,17 @@ static void omap_write_buf_pref(struct mtd_info *mtd,  				iowrite16(*p++, info->nand.IO_ADDR_W);  		}  		/* wait for data to flushed-out before reset the prefetch */ -		do { -			pref_count = gpmc_read_status(GPMC_PREFETCH_COUNT); -		} while (pref_count); +		tim = 0; +		limit = (loops_per_jiffy * +					msecs_to_jiffies(OMAP_NAND_TIMEOUT_MS)); +		while (gpmc_read_status(GPMC_PREFETCH_COUNT) && (tim++ < limit)) +			cpu_relax(); +  		/* disable and stop the PFPW engine */  		gpmc_prefetch_reset(info->gpmc_cs);  	}  } -#ifdef CONFIG_MTD_NAND_OMAP_PREFETCH_DMA  /*   * omap_nand_dma_cb: callback on the completion of dma transfer   * @lch: logical channel @@ -348,14 +355,15 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr,  {  	struct omap_nand_info *info = container_of(mtd,  					struct omap_nand_info, mtd); -	uint32_t prefetch_status = 0;  	enum dma_data_direction dir = is_write ? DMA_TO_DEVICE :  							DMA_FROM_DEVICE;  	dma_addr_t dma_addr;  	int ret; +	unsigned long tim, limit; -	/* 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; @@ -396,9 +404,10 @@ 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, +			PREFETCH_FIFOTHRESHOLD_MAX, 0x1, len, is_write);  	if (ret) -		/* PFPW engine is busy, use cpu copy methode */ +		/* PFPW engine is busy, use cpu copy method */  		goto out_copy;  	init_completion(&info->comp); @@ -407,10 +416,11 @@ 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); +	tim = 0; +	limit = (loops_per_jiffy * msecs_to_jiffies(OMAP_NAND_TIMEOUT_MS)); +	while (gpmc_read_status(GPMC_PREFETCH_COUNT) && (tim++ < limit)) +		cpu_relax(); -	do { -		prefetch_status = gpmc_read_status(GPMC_PREFETCH_COUNT); -	} while (prefetch_status);  	/* disable and stop the PFPW engine */  	gpmc_prefetch_reset(info->gpmc_cs); @@ -426,14 +436,6 @@ out_copy:  			: omap_write_buf8(mtd, (u_char *) addr, len);  	return 0;  } -#else -static void omap_nand_dma_cb(int lch, u16 ch_status, void *data) {} -static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr, -					unsigned int len, int is_write) -{ -	return 0; -} -#endif  /**   * omap_read_buf_dma_pref - read data from NAND controller into buffer @@ -466,6 +468,157 @@ 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 bytes; +	u32 irq_stat; + +	irq_stat = gpmc_read_status(GPMC_GET_IRQ_STATUS); +	bytes = gpmc_read_status(GPMC_PREFETCH_FIFO_CNT); +	bytes = bytes  & 0xFFFC; /* io in multiple of 4 bytes */ +	if (info->iomode == OMAP_NAND_IO_WRITE) { /* checks for write io */ +		if (irq_stat & 0x2) +			goto done; + +		if (info->buf_len && (info->buf_len < bytes)) +			bytes = info->buf_len; +		else if (!info->buf_len) +			bytes = 0; +		iowrite32_rep(info->nand.IO_ADDR_W, +						(u32 *)info->buf, bytes >> 2); +		info->buf = info->buf + bytes; +		info->buf_len -= bytes; + +	} else { +		ioread32_rep(info->nand.IO_ADDR_R, +						(u32 *)info->buf, bytes >> 2); +		info->buf = info->buf + bytes; + +		if (irq_stat & 0x2) +			goto done; +	} +	gpmc_cs_configure(info->gpmc_cs, GPMC_SET_IRQ_STATUS, irq_stat); + +	return IRQ_HANDLED; + +done: +	complete(&info->comp); +	/* disable irq */ +	gpmc_cs_configure(info->gpmc_cs, GPMC_ENABLE_IRQ, 0); + +	/* clear status */ +	gpmc_cs_configure(info->gpmc_cs, GPMC_SET_IRQ_STATUS, irq_stat); + +	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); +	int ret = 0; + +	if (len <= mtd->oobsize) { +		omap_read_buf_pref(mtd, buf, len); +		return; +	} + +	info->iomode = OMAP_NAND_IO_READ; +	info->buf = buf; +	init_completion(&info->comp); + +	/*  configure and start prefetch transfer */ +	ret = gpmc_prefetch_enable(info->gpmc_cs, +			PREFETCH_FIFOTHRESHOLD_MAX/2, 0x0, len, 0x0); +	if (ret) +		/* PFPW engine is busy, use cpu copy method */ +		goto out_copy; + +	info->buf_len = len; +	/* enable irq */ +	gpmc_cs_configure(info->gpmc_cs, GPMC_ENABLE_IRQ, +		(GPMC_IRQ_FIFOEVENTENABLE | GPMC_IRQ_COUNT_EVENT)); + +	/* waiting for read to complete */ +	wait_for_completion(&info->comp); + +	/* disable and stop the PFPW engine */ +	gpmc_prefetch_reset(info->gpmc_cs); +	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); +	int ret = 0; +	unsigned long tim, limit; + +	if (len <= mtd->oobsize) { +		omap_write_buf_pref(mtd, buf, len); +		return; +	} + +	info->iomode = OMAP_NAND_IO_WRITE; +	info->buf = (u_char *) buf; +	init_completion(&info->comp); + +	/* configure and start prefetch transfer : size=24 */ +	ret = gpmc_prefetch_enable(info->gpmc_cs, +			(PREFETCH_FIFOTHRESHOLD_MAX * 3) / 8, 0x0, len, 0x1); +	if (ret) +		/* PFPW engine is busy, use cpu copy method */ +		goto out_copy; + +	info->buf_len = len; +	/* enable irq */ +	gpmc_cs_configure(info->gpmc_cs, GPMC_ENABLE_IRQ, +			(GPMC_IRQ_FIFOEVENTENABLE | GPMC_IRQ_COUNT_EVENT)); + +	/* waiting for write to complete */ +	wait_for_completion(&info->comp); +	/* wait for data to flushed-out before reset the prefetch */ +	tim = 0; +	limit = (loops_per_jiffy *  msecs_to_jiffies(OMAP_NAND_TIMEOUT_MS)); +	while (gpmc_read_status(GPMC_PREFETCH_COUNT) && (tim++ < limit)) +		cpu_relax(); + +	/* disable and stop the PFPW engine */ +	gpmc_prefetch_reset(info->gpmc_cs); +	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 @@ -487,8 +640,6 @@ static int omap_verify_buf(struct mtd_info *mtd, const u_char * buf, int len)  	return 0;  } -#ifdef CONFIG_MTD_NAND_OMAP_HWECC -  /**   * gen_true_ecc - This function will generate true ECC value   * @ecc_buf: buffer to store ecc code @@ -708,8 +859,6 @@ static void omap_enable_hwecc(struct mtd_info *mtd, int mode)  	gpmc_enable_hwecc(info->gpmc_cs, mode, dev_width, info->nand.ecc.size);  } -#endif -  /**   * omap_wait - wait until the command is done   * @mtd: MTD device structure @@ -779,6 +928,7 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)  	struct omap_nand_info		*info;  	struct omap_nand_platform_data	*pdata;  	int				err; +	int				i, offset;  	pdata = pdev->dev.platform_data;  	if (pdata == NULL) { @@ -804,7 +954,7 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)  	info->mtd.name		= dev_name(&pdev->dev);  	info->mtd.owner		= THIS_MODULE; -	info->nand.options	|= pdata->devsize ? NAND_BUSWIDTH_16 : 0; +	info->nand.options	= pdata->devsize;  	info->nand.options	|= NAND_SKIP_BBTSCAN;  	/* NAND write protect off */ @@ -842,28 +992,13 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)  		info->nand.chip_delay = 50;  	} -	if (use_prefetch) { - +	switch (pdata->xfer_type) { +	case NAND_OMAP_PREFETCH_POLLED:  		info->nand.read_buf   = omap_read_buf_pref;  		info->nand.write_buf  = omap_write_buf_pref; -		if (use_dma) { -			err = omap_request_dma(OMAP24XX_DMA_GPMC, "NAND", -				omap_nand_dma_cb, &info->comp, &info->dma_ch); -			if (err < 0) { -				info->dma_ch = -1; -				printk(KERN_WARNING "DMA request failed." -					" Non-dma data transfer mode\n"); -			} else { -				omap_set_dma_dest_burst_mode(info->dma_ch, -						OMAP_DMA_DATA_BURST_16); -				omap_set_dma_src_burst_mode(info->dma_ch, -						OMAP_DMA_DATA_BURST_16); +		break; -				info->nand.read_buf   = omap_read_buf_dma_pref; -				info->nand.write_buf  = omap_write_buf_dma_pref; -			} -		} -	} else { +	case NAND_OMAP_POLLED:  		if (info->nand.options & NAND_BUSWIDTH_16) {  			info->nand.read_buf   = omap_read_buf16;  			info->nand.write_buf  = omap_write_buf16; @@ -871,20 +1006,61 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)  			info->nand.read_buf   = omap_read_buf8;  			info->nand.write_buf  = omap_write_buf8;  		} +		break; + +	case NAND_OMAP_PREFETCH_DMA: +		err = omap_request_dma(OMAP24XX_DMA_GPMC, "NAND", +				omap_nand_dma_cb, &info->comp, &info->dma_ch); +		if (err < 0) { +			info->dma_ch = -1; +			dev_err(&pdev->dev, "DMA request failed!\n"); +			goto out_release_mem_region; +		} else { +			omap_set_dma_dest_burst_mode(info->dma_ch, +					OMAP_DMA_DATA_BURST_16); +			omap_set_dma_src_burst_mode(info->dma_ch, +					OMAP_DMA_DATA_BURST_16); + +			info->nand.read_buf   = omap_read_buf_dma_pref; +			info->nand.write_buf  = omap_write_buf_dma_pref; +		} +		break; + +	case NAND_OMAP_PREFETCH_IRQ: +		err = request_irq(pdata->gpmc_irq, +				omap_nand_irq, IRQF_SHARED, "gpmc-nand", info); +		if (err) { +			dev_err(&pdev->dev, "requesting irq(%d) error:%d", +							pdata->gpmc_irq, err); +			goto out_release_mem_region; +		} else { +			info->gpmc_irq	     = pdata->gpmc_irq; +			info->nand.read_buf  = omap_read_buf_irq_pref; +			info->nand.write_buf = omap_write_buf_irq_pref; +		} +		break; + +	default: +		dev_err(&pdev->dev, +			"xfer_type(%d) not supported!\n", pdata->xfer_type); +		err = -EINVAL; +		goto out_release_mem_region;  	} -	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; +	info->nand.verify_buf = omap_verify_buf; -#else -	info->nand.ecc.mode = NAND_ECC_SOFT; -#endif +	/* selsect the ecc type */ +	if (pdata->ecc_opt == OMAP_ECC_HAMMING_CODE_DEFAULT) +		info->nand.ecc.mode = NAND_ECC_SOFT; +	else if ((pdata->ecc_opt == OMAP_ECC_HAMMING_CODE_HW) || +		(pdata->ecc_opt == OMAP_ECC_HAMMING_CODE_HW_ROMCODE)) { +		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; +	}  	/* DIP switches on some boards change between 8 and 16 bit  	 * bus widths for flash.  Try the other width if the first try fails. @@ -897,6 +1073,26 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)  		}  	} +	/* rom code layout */ +	if (pdata->ecc_opt == OMAP_ECC_HAMMING_CODE_HW_ROMCODE) { + +		if (info->nand.options & NAND_BUSWIDTH_16) +			offset = 2; +		else { +			offset = 1; +			info->nand.badblock_pattern = &bb_descrip_flashbased; +		} +		omap_oobinfo.eccbytes = 3 * (info->mtd.oobsize/16); +		for (i = 0; i < omap_oobinfo.eccbytes; i++) +			omap_oobinfo.eccpos[i] = i+offset; + +		omap_oobinfo.oobfree->offset = offset + omap_oobinfo.eccbytes; +		omap_oobinfo.oobfree->length = info->mtd.oobsize - +					(offset + omap_oobinfo.eccbytes); + +		info->nand.ecc.layout = &omap_oobinfo; +	} +  #ifdef CONFIG_MTD_PARTITIONS  	err = parse_mtd_partitions(&info->mtd, part_probes, &info->parts, 0);  	if (err > 0) @@ -926,9 +1122,12 @@ static int omap_nand_remove(struct platform_device *pdev)  							mtd);  	platform_set_drvdata(pdev, NULL); -	if (use_dma) +	if (info->dma_ch != -1)  		omap_free_dma(info->dma_ch); +	if (info->gpmc_irq) +		free_irq(info->gpmc_irq, info); +  	/* Release NAND device, its internal structures and partitions */  	nand_release(&info->mtd);  	iounmap(info->nand.IO_ADDR_R); @@ -947,16 +1146,8 @@ static struct platform_driver omap_nand_driver = {  static int __init omap_nand_init(void)  { -	printk(KERN_INFO "%s driver initializing\n", DRIVER_NAME); +	pr_info("%s driver initializing\n", DRIVER_NAME); -	/* 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"); -	}  	return platform_driver_register(&omap_nand_driver);  } diff --git a/drivers/mtd/nand/r852.c b/drivers/mtd/nand/r852.c index d9d7efbc77c..6322d1fb5d6 100644 --- a/drivers/mtd/nand/r852.c +++ b/drivers/mtd/nand/r852.c @@ -930,7 +930,7 @@ int  r852_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)  	init_completion(&dev->dma_done); -	dev->card_workqueue = create_freezeable_workqueue(DRV_NAME); +	dev->card_workqueue = create_freezable_workqueue(DRV_NAME);  	if (!dev->card_workqueue)  		goto error9; diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c index ac31f461cc1..ec26399e3cf 100644 --- a/drivers/mtd/onenand/omap2.c +++ b/drivers/mtd/onenand/omap2.c @@ -63,7 +63,7 @@ struct omap2_onenand {  	struct completion dma_done;  	int dma_channel;  	int freq; -	int (*setup)(void __iomem *base, int freq); +	int (*setup)(void __iomem *base, int *freq_ptr);  	struct regulator *regulator;  }; @@ -148,11 +148,9 @@ static int omap2_onenand_wait(struct mtd_info *mtd, int state)  			wait_err("controller error", state, ctrl, intr);  			return -EIO;  		} -		if ((intr & intr_flags) != intr_flags) { -			wait_err("timeout", state, ctrl, intr); -			return -EIO; -		} -		return 0; +		if ((intr & intr_flags) == intr_flags) +			return 0; +		/* Continue in wait for interrupt branch */  	}  	if (state != FL_READING) { @@ -581,7 +579,7 @@ static int __adjust_timing(struct device *dev, void *data)  	/* DMA is not in use so this is all that is needed */  	/* Revisit for OMAP3! */ -	ret = c->setup(c->onenand.base, c->freq); +	ret = c->setup(c->onenand.base, &c->freq);  	return ret;  } @@ -673,7 +671,7 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev)  	}  	if (pdata->onenand_setup != NULL) { -		r = pdata->onenand_setup(c->onenand.base, c->freq); +		r = pdata->onenand_setup(c->onenand.base, &c->freq);  		if (r < 0) {  			dev_err(&pdev->dev, "Onenand platform setup failed: "  				"%d\n", r); @@ -718,8 +716,8 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev)  	}  	dev_info(&pdev->dev, "initializing on CS%d, phys base 0x%08lx, virtual " -		 "base %p\n", c->gpmc_cs, c->phys_base, -		 c->onenand.base); +		 "base %p, freq %d MHz\n", c->gpmc_cs, c->phys_base, +		 c->onenand.base, c->freq);  	c->pdev = pdev;  	c->mtd.name = dev_name(&pdev->dev); @@ -754,24 +752,6 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev)  	if ((r = onenand_scan(&c->mtd, 1)) < 0)  		goto err_release_regulator; -	switch ((c->onenand.version_id >> 4) & 0xf) { -	case 0: -		c->freq = 40; -		break; -	case 1: -		c->freq = 54; -		break; -	case 2: -		c->freq = 66; -		break; -	case 3: -		c->freq = 83; -		break; -	case 4: -		c->freq = 104; -		break; -	} -  #ifdef CONFIG_MTD_PARTITIONS  	r = parse_mtd_partitions(&c->mtd, part_probes, &c->parts, 0);  	if (r > 0) diff --git a/drivers/mtd/sm_ftl.c b/drivers/mtd/sm_ftl.c index 67822cf6c02..ac0d6a8613b 100644 --- a/drivers/mtd/sm_ftl.c +++ b/drivers/mtd/sm_ftl.c @@ -1258,7 +1258,7 @@ static struct mtd_blktrans_ops sm_ftl_ops = {  static __init int sm_module_init(void)  {  	int error = 0; -	cache_flush_workqueue = create_freezeable_workqueue("smflush"); +	cache_flush_workqueue = create_freezable_workqueue("smflush");  	if (IS_ERR(cache_flush_workqueue))  		return PTR_ERR(cache_flush_workqueue);  |