Commit 623ff773 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'for-linus-3.4' of git://git.infradead.org/mtd-2.6

Pull MTD changes from David Woodhouse:
 - Artem's cleanup of the MTD API continues apace.
 - Fixes and improvements for ST FSMC and SuperH FLCTL NAND, amongst
   others.
 - More work on DiskOnChip G3, new driver for DiskOnChip G4.
 - Clean up debug/warning printks in JFFS2 to use pr_<level>.

Fix up various trivial conflicts, largely due to changes in calling
conventions for things like dmaengine_prep_slave_sg() (new inline
wrapper to hide new parameter, clashing with rewrite of previously last
parameter that used to be an 'append' flag, and is now a bitmap of
'unsigned long flags').

(Also some header file fallout - like so many merges this merge window -
and silly conflicts with sparse fixes)

* tag 'for-linus-3.4' of git://git.infradead.org/mtd-2.6: (120 commits)
  mtd: docg3 add protection against concurrency
  mtd: docg3 refactor cascade floors structure
  mtd: docg3 increase write/erase timeout
  mtd: docg3 fix inbound calculations
  mtd: nand: gpmi: fix function annotations
  mtd: phram: fix section mismatch for phram_setup
  mtd: unify initialization of erase_info->fail_addr
  mtd: support ONFI multi lun NAND
  mtd: sm_ftl: fix typo in major number.
  mtd: add device-tree support to spear_smi
  mtd: spear_smi: Remove default partition information from driver
  mtd: Add device-tree support to fsmc_nand
  mtd: fix section mismatch for doc_probe_device
  mtd: nand/fsmc: Remove sparse warnings and errors
  mtd: nand/fsmc: Add DMA support
  mtd: nand/fsmc: Access the NAND device word by word whenever possible
  mtd: nand/fsmc: Use dev_err to report error scenario
  mtd: nand/fsmc: Use devm routines
  mtd: nand/fsmc: Modify fsmc driver to accept nand timing parameters via platform
  mtd: fsmc_nand: add pm callbacks to support hibernation
  ...
parents c39e8ede 7b0e67f6
* FSMC NAND
Required properties:
- compatible : "st,spear600-fsmc-nand"
- reg : Address range of the mtd chip
- reg-names: Should contain the reg names "fsmc_regs" and "nand_data"
- st,ale-off : Chip specific offset to ALE
- st,cle-off : Chip specific offset to CLE
Optional properties:
- bank-width : Width (in bytes) of the device. If not present, the width
defaults to 1 byte
- nand-skip-bbtscan: Indicates the the BBT scanning should be skipped
Example:
fsmc: flash@d1800000 {
compatible = "st,spear600-fsmc-nand";
#address-cells = <1>;
#size-cells = <1>;
reg = <0xd1800000 0x1000 /* FSMC Register */
0xd2000000 0x4000>; /* NAND Base */
reg-names = "fsmc_regs", "nand_data";
st,ale-off = <0x20000>;
st,cle-off = <0x10000>;
bank-width = <1>;
nand-skip-bbtscan;
partition@0 {
...
};
};
* SPEAr SMI
Required properties:
- compatible : "st,spear600-smi"
- reg : Address range of the mtd chip
- #address-cells, #size-cells : Must be present if the device has sub-nodes
representing partitions.
- interrupt-parent: Should be the phandle for the interrupt controller
that services interrupts for this device
- interrupts: Should contain the STMMAC interrupts
- clock-rate : Functional clock rate of SMI in Hz
Optional properties:
- st,smi-fast-mode : Flash supports read in fast mode
Example:
smi: flash@fc000000 {
compatible = "st,spear600-smi";
#address-cells = <1>;
#size-cells = <1>;
reg = <0xfc000000 0x1000>;
interrupt-parent = <&vic1>;
interrupts = <12>;
clock-rate = <50000000>; /* 50MHz */
flash@f8000000 {
st,smi-fast-mode;
...
};
};
......@@ -17,20 +17,12 @@
void omap1_set_vpp(struct platform_device *pdev, int enable)
{
static int count;
u32 l;
if (enable) {
if (count++ == 0) {
l = omap_readl(EMIFS_CONFIG);
l |= OMAP_EMIFS_CONFIG_WP;
omap_writel(l, EMIFS_CONFIG);
}
} else {
if (count && (--count == 0)) {
l = omap_readl(EMIFS_CONFIG);
l &= ~OMAP_EMIFS_CONFIG_WP;
omap_writel(l, EMIFS_CONFIG);
}
}
l = omap_readl(EMIFS_CONFIG);
if (enable)
l |= OMAP_EMIFS_CONFIG_WP;
else
l &= ~OMAP_EMIFS_CONFIG_WP;
omap_writel(l, EMIFS_CONFIG);
}
......@@ -35,9 +35,7 @@
static void simtec_nor_vpp(struct platform_device *pdev, int vpp)
{
unsigned int val;
unsigned long flags;
local_irq_save(flags);
val = __raw_readb(BAST_VA_CTRL3);
printk(KERN_DEBUG "%s(%d)\n", __func__, vpp);
......@@ -48,7 +46,6 @@ static void simtec_nor_vpp(struct platform_device *pdev, int vpp)
val &= ~BAST_CPLD_CTRL3_ROMWEN;
__raw_writeb(val, BAST_VA_CTRL3);
local_irq_restore(flags);
}
static struct physmap_flash_data simtec_nor_pdata = {
......
......@@ -39,6 +39,7 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/physmap.h>
#include <linux/mtd/sh_flctl.h>
#include <linux/pm_clock.h>
#include <linux/smsc911x.h>
#include <linux/sh_intc.h>
......@@ -956,6 +957,50 @@ static struct platform_device fsi_ak4643_device = {
},
};
/* FLCTL */
static struct mtd_partition nand_partition_info[] = {
{
.name = "system",
.offset = 0,
.size = 128 * 1024 * 1024,
},
{
.name = "userdata",
.offset = MTDPART_OFS_APPEND,
.size = 256 * 1024 * 1024,
},
{
.name = "cache",
.offset = MTDPART_OFS_APPEND,
.size = 128 * 1024 * 1024,
},
};
static struct resource nand_flash_resources[] = {
[0] = {
.start = 0xe6a30000,
.end = 0xe6a3009b,
.flags = IORESOURCE_MEM,
}
};
static struct sh_flctl_platform_data nand_flash_data = {
.parts = nand_partition_info,
.nr_parts = ARRAY_SIZE(nand_partition_info),
.flcmncr_val = CLK_16B_12L_4H | TYPESEL_SET
| SHBUSSEL | SEL_16BIT | SNAND_E,
.use_holden = 1,
};
static struct platform_device nand_flash_device = {
.name = "sh_flctl",
.resource = nand_flash_resources,
.num_resources = ARRAY_SIZE(nand_flash_resources),
.dev = {
.platform_data = &nand_flash_data,
},
};
/*
* The card detect pin of the top SD/MMC slot (CN7) is active low and is
* connected to GPIO A22 of SH7372 (GPIO_PORT41).
......@@ -1259,6 +1304,7 @@ static struct platform_device *mackerel_devices[] __initdata = {
&fsi_device,
&fsi_ak4643_device,
&fsi_hdmi_device,
&nand_flash_device,
&sdhi0_device,
#if !defined(CONFIG_MMC_SH_MMCIF) && !defined(CONFIG_MMC_SH_MMCIF_MODULE)
&sdhi1_device,
......@@ -1488,6 +1534,30 @@ static void __init mackerel_init(void)
gpio_request(GPIO_FN_MMCCMD0, NULL);
gpio_request(GPIO_FN_MMCCLK0, NULL);
/* FLCTL */
gpio_request(GPIO_FN_D0_NAF0, NULL);
gpio_request(GPIO_FN_D1_NAF1, NULL);
gpio_request(GPIO_FN_D2_NAF2, NULL);
gpio_request(GPIO_FN_D3_NAF3, NULL);
gpio_request(GPIO_FN_D4_NAF4, NULL);
gpio_request(GPIO_FN_D5_NAF5, NULL);
gpio_request(GPIO_FN_D6_NAF6, NULL);
gpio_request(GPIO_FN_D7_NAF7, NULL);
gpio_request(GPIO_FN_D8_NAF8, NULL);
gpio_request(GPIO_FN_D9_NAF9, NULL);
gpio_request(GPIO_FN_D10_NAF10, NULL);
gpio_request(GPIO_FN_D11_NAF11, NULL);
gpio_request(GPIO_FN_D12_NAF12, NULL);
gpio_request(GPIO_FN_D13_NAF13, NULL);
gpio_request(GPIO_FN_D14_NAF14, NULL);
gpio_request(GPIO_FN_D15_NAF15, NULL);
gpio_request(GPIO_FN_FCE0, NULL);
gpio_request(GPIO_FN_WE0_FWE, NULL);
gpio_request(GPIO_FN_FRB, NULL);
gpio_request(GPIO_FN_A4_FOE, NULL);
gpio_request(GPIO_FN_A5_FCDE, NULL);
gpio_request(GPIO_FN_RD_FSC, NULL);
/* enable GPS module (GT-720F) */
gpio_request(GPIO_FN_SCIFA2_TXD1, NULL);
gpio_request(GPIO_FN_SCIFA2_RXD1, NULL);
......@@ -1532,6 +1602,7 @@ static void __init mackerel_init(void)
sh7372_add_device_to_domain(&sh7372_a4mp, &fsi_device);
sh7372_add_device_to_domain(&sh7372_a3sp, &usbhs0_device);
sh7372_add_device_to_domain(&sh7372_a3sp, &usbhs1_device);
sh7372_add_device_to_domain(&sh7372_a3sp, &nand_flash_device);
sh7372_add_device_to_domain(&sh7372_a3sp, &sh_mmcif_device);
sh7372_add_device_to_domain(&sh7372_a3sp, &sdhi0_device);
#if !defined(CONFIG_MMC_SH_MMCIF) && !defined(CONFIG_MMC_SH_MMCIF_MODULE)
......
......@@ -511,7 +511,7 @@ enum { MSTP001, MSTP000,
MSTP223,
MSTP218, MSTP217, MSTP216, MSTP214, MSTP208, MSTP207,
MSTP206, MSTP205, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200,
MSTP328, MSTP323, MSTP322, MSTP314, MSTP313, MSTP312,
MSTP328, MSTP323, MSTP322, MSTP315, MSTP314, MSTP313, MSTP312,
MSTP423, MSTP415, MSTP413, MSTP411, MSTP410, MSTP407, MSTP406,
MSTP405, MSTP404, MSTP403, MSTP400,
MSTP_NR };
......@@ -553,6 +553,7 @@ static struct clk mstp_clks[MSTP_NR] = {
[MSTP328] = MSTP(&div6_clks[DIV6_SPU], SMSTPCR3, 28, 0), /* FSI2 */
[MSTP323] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR3, 23, 0), /* IIC1 */
[MSTP322] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR3, 22, 0), /* USB0 */
[MSTP315] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 15, 0), /* FLCTL*/
[MSTP314] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 14, 0), /* SDHI0 */
[MSTP313] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 13, 0), /* SDHI1 */
[MSTP312] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 12, 0), /* MMC */
......@@ -653,6 +654,7 @@ static struct clk_lookup lookups[] = {
CLKDEV_DEV_ID("r8a66597_hcd.0", &mstp_clks[MSTP322]), /* USB0 */
CLKDEV_DEV_ID("r8a66597_udc.0", &mstp_clks[MSTP322]), /* USB0 */
CLKDEV_DEV_ID("renesas_usbhs.0", &mstp_clks[MSTP322]), /* USB0 */
CLKDEV_DEV_ID("sh_flctl.0", &mstp_clks[MSTP315]), /* FLCTL */
CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]), /* SDHI0 */
CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]), /* SDHI1 */
CLKDEV_DEV_ID("sh_mmcif.0", &mstp_clks[MSTP312]), /* MMC */
......
......@@ -1544,6 +1544,8 @@ static struct fsmc_nand_platform_data nand_platform_data = {
.nr_partitions = ARRAY_SIZE(u300_partitions),
.options = NAND_SKIP_BBTSCAN,
.width = FSMC_NAND_BW8,
.ale_off = PLAT_NAND_ALE,
.cle_off = PLAT_NAND_CLE,
};
static struct platform_device nand_device = {
......
......@@ -24,6 +24,11 @@
/* NFIF */
#define U300_NAND_IF_PHYS_BASE 0x9f800000
/* ALE, CLE offset for FSMC NAND */
#define PLAT_NAND_CLE (1 << 16)
#define PLAT_NAND_ALE (1 << 17)
/* AHB Peripherals */
#define U300_AHB_PER_PHYS_BASE 0xa0000000
#define U300_AHB_PER_VIRT_BASE 0xff010000
......
......@@ -60,7 +60,7 @@ static int __init flash_init(void)
if (mymtd) {
mymtd->owner = THIS_MODULE;
mtd_device_parse_register(mymtd, part_probe_types,
0, NULL, 0);
NULL, NULL, 0);
} else {
pr_err("Failed to register MTD device for flash\n");
}
......
......@@ -22,10 +22,10 @@
#include <linux/platform_device.h>
#include <linux/dmaengine.h>
#include <linux/delay.h>
#include <linux/fsl/mxs-dma.h>
#include <asm/irq.h>
#include <mach/mxs.h>
#include <mach/dma.h>
#include <mach/common.h>
#include "dmaengine.h"
......@@ -337,10 +337,32 @@ static void mxs_dma_free_chan_resources(struct dma_chan *chan)
clk_disable_unprepare(mxs_dma->clk);
}
/*
* How to use the flags for ->device_prep_slave_sg() :
* [1] If there is only one DMA command in the DMA chain, the code should be:
* ......
* ->device_prep_slave_sg(DMA_CTRL_ACK);
* ......
* [2] If there are two DMA commands in the DMA chain, the code should be
* ......
* ->device_prep_slave_sg(0);
* ......
* ->device_prep_slave_sg(DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
* ......
* [3] If there are more than two DMA commands in the DMA chain, the code
* should be:
* ......
* ->device_prep_slave_sg(0); // First
* ......
* ->device_prep_slave_sg(DMA_PREP_INTERRUPT [| DMA_CTRL_ACK]);
* ......
* ->device_prep_slave_sg(DMA_PREP_INTERRUPT | DMA_CTRL_ACK); // Last
* ......
*/
static struct dma_async_tx_descriptor *mxs_dma_prep_slave_sg(
struct dma_chan *chan, struct scatterlist *sgl,
unsigned int sg_len, enum dma_transfer_direction direction,
unsigned long append, void *context)
unsigned long flags, void *context)
{
struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan);
struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
......@@ -348,6 +370,7 @@ static struct dma_async_tx_descriptor *mxs_dma_prep_slave_sg(
struct scatterlist *sg;
int i, j;
u32 *pio;
bool append = flags & DMA_PREP_INTERRUPT;
int idx = append ? mxs_chan->desc_count : 0;
if (mxs_chan->status == DMA_IN_PROGRESS && !append)
......@@ -374,7 +397,6 @@ static struct dma_async_tx_descriptor *mxs_dma_prep_slave_sg(
ccw->bits |= CCW_CHAIN;
ccw->bits &= ~CCW_IRQ;
ccw->bits &= ~CCW_DEC_SEM;
ccw->bits &= ~CCW_WAIT4END;
} else {
idx = 0;
}
......@@ -389,7 +411,8 @@ static struct dma_async_tx_descriptor *mxs_dma_prep_slave_sg(
ccw->bits = 0;
ccw->bits |= CCW_IRQ;
ccw->bits |= CCW_DEC_SEM;
ccw->bits |= CCW_WAIT4END;
if (flags & DMA_CTRL_ACK)
ccw->bits |= CCW_WAIT4END;
ccw->bits |= CCW_HALT_ON_TERM;
ccw->bits |= CCW_TERM_FLUSH;
ccw->bits |= BF_CCW(sg_len, PIO_NUM);
......@@ -420,7 +443,8 @@ static struct dma_async_tx_descriptor *mxs_dma_prep_slave_sg(
ccw->bits &= ~CCW_CHAIN;
ccw->bits |= CCW_IRQ;
ccw->bits |= CCW_DEC_SEM;
ccw->bits |= CCW_WAIT4END;
if (flags & DMA_CTRL_ACK)
ccw->bits |= CCW_WAIT4END;
}
}
}
......
......@@ -38,10 +38,10 @@
#include <linux/gpio.h>
#include <linux/regulator/consumer.h>
#include <linux/module.h>
#include <linux/fsl/mxs-dma.h>
#include <mach/mxs.h>
#include <mach/common.h>
#include <mach/dma.h>
#include <mach/mmc.h>
#define DRIVER_NAME "mxs-mmc"
......@@ -305,7 +305,7 @@ static irqreturn_t mxs_mmc_irq_handler(int irq, void *dev_id)
}
static struct dma_async_tx_descriptor *mxs_mmc_prep_dma(
struct mxs_mmc_host *host, unsigned int append)
struct mxs_mmc_host *host, unsigned long flags)
{
struct dma_async_tx_descriptor *desc;
struct mmc_data *data = host->data;
......@@ -325,7 +325,7 @@ static struct dma_async_tx_descriptor *mxs_mmc_prep_dma(
}
desc = dmaengine_prep_slave_sg(host->dmach,
sgl, sg_len, host->slave_dirn, append);
sgl, sg_len, host->slave_dirn, flags);
if (desc) {
desc->callback = mxs_mmc_dma_irq_callback;
desc->callback_param = host;
......@@ -358,7 +358,7 @@ static void mxs_mmc_bc(struct mxs_mmc_host *host)
host->ssp_pio_words[2] = cmd1;
host->dma_dir = DMA_NONE;
host->slave_dirn = DMA_TRANS_NONE;
desc = mxs_mmc_prep_dma(host, 0);
desc = mxs_mmc_prep_dma(host, DMA_CTRL_ACK);
if (!desc)
goto out;
......@@ -398,7 +398,7 @@ static void mxs_mmc_ac(struct mxs_mmc_host *host)
host->ssp_pio_words[2] = cmd1;
host->dma_dir = DMA_NONE;
host->slave_dirn = DMA_TRANS_NONE;
desc = mxs_mmc_prep_dma(host, 0);
desc = mxs_mmc_prep_dma(host, DMA_CTRL_ACK);
if (!desc)
goto out;
......@@ -526,7 +526,7 @@ static void mxs_mmc_adtc(struct mxs_mmc_host *host)
host->data = data;
host->dma_dir = dma_data_dir;
host->slave_dirn = slave_dirn;
desc = mxs_mmc_prep_dma(host, 1);
desc = mxs_mmc_prep_dma(host, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!desc)
goto out;
......
......@@ -304,9 +304,6 @@ config MTD_OOPS
buffer in a flash partition where it can be read back at some
later point.
To use, add console=ttyMTDx to the kernel command line,
where x is the MTD device number to use.
config MTD_SWAP
tristate "Swap on MTD device support"
depends on MTD && SWAP
......
......@@ -87,7 +87,7 @@ static int cfi_intelext_partition_fixup(struct mtd_info *, struct cfi_private **
static int cfi_intelext_point (struct mtd_info *mtd, loff_t from, size_t len,
size_t *retlen, void **virt, resource_size_t *phys);
static void cfi_intelext_unpoint(struct mtd_info *mtd, loff_t from, size_t len);
static int cfi_intelext_unpoint(struct mtd_info *mtd, loff_t from, size_t len);
static int chip_ready (struct map_info *map, struct flchip *chip, unsigned long adr, int mode);
static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr, int mode);
......@@ -262,9 +262,9 @@ static void fixup_st_m28w320cb(struct mtd_info *mtd)
static void fixup_use_point(struct mtd_info *mtd)
{
struct map_info *map = mtd->priv;
if (!mtd->point && map_is_linear(map)) {
mtd->point = cfi_intelext_point;
mtd->unpoint = cfi_intelext_unpoint;
if (!mtd->_point && map_is_linear(map)) {
mtd->_point = cfi_intelext_point;
mtd->_unpoint = cfi_intelext_unpoint;
}
}
......@@ -274,8 +274,8 @@ static void fixup_use_write_buffers(struct mtd_info *mtd)
struct cfi_private *cfi = map->fldrv_priv;
if (cfi->cfiq->BufWriteTimeoutTyp) {
printk(KERN_INFO "Using buffer write method\n" );
mtd->write = cfi_intelext_write_buffers;
mtd->writev = cfi_intelext_writev;
mtd->_write = cfi_intelext_write_buffers;
mtd->_writev = cfi_intelext_writev;
}
}
......@@ -443,15 +443,15 @@ struct mtd_info *cfi_cmdset_0001(struct map_info *map, int primary)
mtd->type = MTD_NORFLASH;
/* Fill in the default mtd operations */
mtd->erase = cfi_intelext_erase_varsize;
mtd->read = cfi_intelext_read;
mtd->write = cfi_intelext_write_words;
mtd->sync = cfi_intelext_sync;
mtd->lock = cfi_intelext_lock;
mtd->unlock = cfi_intelext_unlock;
mtd->is_locked = cfi_intelext_is_locked;
mtd->suspend = cfi_intelext_suspend;
mtd->resume = cfi_intelext_resume;
mtd->_erase = cfi_intelext_erase_varsize;
mtd->_read = cfi_intelext_read;
mtd->_write = cfi_intelext_write_words;
mtd->_sync = cfi_intelext_sync;
mtd->_lock = cfi_intelext_lock;
mtd->_unlock = cfi_intelext_unlock;
mtd->_is_locked = cfi_intelext_is_locked;
mtd->_suspend = cfi_intelext_suspend;
mtd->_resume = cfi_intelext_resume;
mtd->flags = MTD_CAP_NORFLASH;
mtd->name = map->name;
mtd->writesize = 1;
......@@ -600,12 +600,12 @@ static struct mtd_info *cfi_intelext_setup(struct mtd_info *mtd)
}
#ifdef CONFIG_MTD_OTP
mtd->read_fact_prot_reg = cfi_intelext_read_fact_prot_reg;
mtd->read_user_prot_reg = cfi_intelext_read_user_prot_reg;
mtd->write_user_prot_reg = cfi_intelext_write_user_prot_reg;
mtd->lock_user_prot_reg = cfi_intelext_lock_user_prot_reg;
mtd->get_fact_prot_info = cfi_intelext_get_fact_prot_info;
mtd->get_user_prot_info = cfi_intelext_get_user_prot_info;
mtd->_read_fact_prot_reg = cfi_intelext_read_fact_prot_reg;
mtd->_read_user_prot_reg = cfi_intelext_read_user_prot_reg;
mtd->_write_user_prot_reg = cfi_intelext_write_user_prot_reg;
mtd->_lock_user_prot_reg = cfi_intelext_lock_user_prot_reg;
mtd->_get_fact_prot_info = cfi_intelext_get_fact_prot_info;
mtd->_get_user_prot_info = cfi_intelext_get_user_prot_info;
#endif
/* This function has the potential to distort the reality
......@@ -1017,8 +1017,6 @@ static void put_chip(struct map_info *map, struct flchip *chip, unsigned long ad
case FL_READY:
case FL_STATUS:
case FL_JEDEC_QUERY:
/* We should really make set_vpp() count, rather than doing this */
DISABLE_VPP(map);
break;
default:
printk(KERN_ERR "%s: put_chip() called with oldstate %d!!\n", map->name, chip->oldstate);
......@@ -1324,7 +1322,7 @@ static int cfi_intelext_point(struct mtd_info *mtd, loff_t from, size_t len,
int chipnum;
int ret = 0;
if (!map->virt || (from + len > mtd->size))
if (!map->virt)
return -EINVAL;
/* Now lock the chip(s) to POINT state */
......@@ -1334,7 +1332,6 @@ static int cfi_intelext_point(struct mtd_info *mtd, loff_t from, size_t len,
ofs = from - (chipnum << cfi->chipshift);
*virt = map->virt + cfi->chips[chipnum].start + ofs;
*retlen = 0;
if (phys)
*phys = map->phys + cfi->chips[chipnum].start + ofs;
......@@ -1369,12 +1366,12 @@ static int cfi_intelext_point(struct mtd_info *mtd, loff_t from, size_t len,
return 0;
}
static void cfi_intelext_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
static int cfi_intelext_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
{
struct map_info *map = mtd->priv;
struct cfi_private *cfi = map->fldrv_priv;
unsigned long ofs;
int chipnum;
int chipnum, err = 0;
/* Now unlock the chip(s) POINT state */
......@@ -1382,7 +1379,7 @@ static void cfi_intelext_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
chipnum = (from >> cfi->chipshift);
ofs = from - (chipnum << cfi->chipshift);
while (len) {
while (len && !err) {
unsigned long thislen;
struct flchip *chip;
......@@ -1400,8 +1397,10 @@ static void cfi_intelext_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
chip->ref_point_counter--;
if(chip->ref_point_counter == 0)
chip->state = FL_READY;
} else
printk(KERN_ERR "%s: Warning: unpoint called on non pointed region\n", map->name); /* Should this give an error? */
} else {
printk(KERN_ERR "%s: Error: unpoint called on non pointed region\n", map->name);
err = -EINVAL;
}
put_chip(map, chip, chip->start);
mutex_unlock(&chip->mutex);
......@@ -1410,6 +1409,8 @@ static void cfi_intelext_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
ofs = 0;
chipnum++;
}
return err;
}
static inline int do_read_onechip(struct map_info *map, struct flchip *chip, loff_t adr, size_t len, u_char *buf)
......@@ -1456,8 +1457,6 @@ static int cfi_intelext_read (struct mtd_info *mtd, loff_t from, size_t len, siz
chipnum = (from >> cfi->chipshift);
ofs = from - (chipnum << cfi->chipshift);
*retlen = 0;
while (len) {
unsigned long thislen;
......@@ -1551,7 +1550,8 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
}
xip_enable(map, chip, adr);
out: put_chip(map, chip, adr);
out: DISABLE_VPP(map);
put_chip(map, chip, adr);
mutex_unlock(&chip->mutex);
return ret;
}
......@@ -1565,10 +1565,6 @@ static int cfi_intelext_write_words (struct mtd_info *mtd, loff_t to , size_t le
int chipnum;
unsigned long ofs;
*retlen = 0;
if (!len)
return 0;
chipnum = to >> cfi->chipshift;
ofs = to - (chipnum << cfi->chipshift);
......@@ -1794,7 +1790,8 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
}
xip_enable(map, chip, cmd_adr);
out: put_chip(map, chip, cmd_adr);
out: DISABLE_VPP(map);
put_chip(map, chip, cmd_adr);
mutex_unlock(&chip->mutex);
return ret;
}
......@@ -1813,7 +1810,6 @@ static int cfi_intelext_writev (struct mtd_info *mtd, const struct kvec *vecs,
for (i = 0; i < count; i++)
len += vecs[i].iov_len;
*retlen = 0;
if (!len)
return 0;
......@@ -1932,6 +1928,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip,
ret = -EIO;
} else if (chipstatus & 0x20 && retries--) {
printk(KERN_DEBUG "block erase failed at 0x%08lx: status 0x%lx. Retrying...\n", adr, chipstatus);
DISABLE_VPP(map);
put_chip(map, chip, adr);
mutex_unlock(&chip->mutex);
goto retry;
......@@ -1944,7 +1941,8 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip,
}
xip_enable(map, chip, adr);
out: put_chip(map, chip, adr);
out: DISABLE_VPP(map);
put_chip(map, chip, adr);
mutex_unlock(&chip->mutex);
return ret;
}
......@@ -2086,7 +2084,8 @@ static int __xipram do_xxlock_oneblock(struct map_info *map, struct flchip *chip
}
xip_enable(map, chip, adr);
out: put_chip(map, chip, adr);
out: DISABLE_VPP(map);
put_chip(map, chip, adr);
mutex_unlock(&chip->mutex);
return ret;
}
......@@ -2483,7 +2482,7 @@ static int cfi_intelext_suspend(struct mtd_info *mtd)
allowed to. Or should we return -EAGAIN, because the upper layers
ought to have already shut down anything which was using the device
anyway? The latter for now. */
printk(KERN_NOTICE "Flash device refused suspend due to active operation (state %d)\n", chip->oldstate);
printk(KERN_NOTICE "Flash device refused suspend due to active operation (state %d)\n", chip->state);
ret = -EAGAIN;
case FL_PM_SUSPENDED:
break;
......
This diff is collapsed.
......@@ -228,15 +228,15 @@ static struct mtd_info *cfi_staa_setup(struct map_info *map)
}
/* Also select the correct geometry setup too */
mtd->erase = cfi_staa_erase_varsize;
mtd->read = cfi_staa_read;
mtd->write = cfi_staa_write_buffers;
mtd->writev = cfi_staa_writev;
mtd->sync = cfi_staa_sync;
mtd->lock = cfi_staa_lock;
mtd->unlock = cfi_staa_unlock;
mtd->suspend = cfi_staa_suspend;
mtd->resume = cfi_staa_resume;
mtd->_erase = cfi_staa_erase_varsize;
mtd->_read = cfi_staa_read;
mtd->_write = cfi_staa_write_buffers;
mtd->_writev = cfi_staa_writev;
mtd->_sync = cfi_staa_sync;
mtd->_lock = cfi_staa_lock;
mtd->_unlock = cfi_staa_unlock;
mtd->_suspend = cfi_staa_suspend;
mtd->_resume = cfi_staa_resume;
mtd->flags = MTD_CAP_NORFLASH & ~MTD_BIT_WRITEABLE;
mtd->writesize = 8; /* FIXME: Should be 0 for STMicro flashes w/out ECC */
mtd->writebufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize;
......@@ -394,8 +394,6 @@ static int cfi_staa_read (struct mtd_info *mtd, loff_t from, size_t len, size_t
chipnum = (from >> cfi->chipshift);
ofs = from - (chipnum << cfi->chipshift);
*retlen = 0;
while (len) {
unsigned long thislen;
......@@ -617,10 +615,6 @@ static int cfi_staa_write_buffers (struct mtd_info *mtd, loff_t to,
int chipnum;
unsigned long ofs;
*retlen = 0;
if (!len)
return 0;
chipnum = to >> cfi->chipshift;
ofs = to - (chipnum << cfi->chipshift);
......@@ -904,12 +898,6 @@ static int cfi_staa_erase_varsize(struct mtd_info *mtd,
int i, first;
struct mtd_erase_region_info *regions = mtd->eraseregions;
if (instr->addr > mtd->size)
return -EINVAL;
if ((instr->len + instr->addr) > mtd->size)
return -EINVAL;
/* Check that both start and end of the requested erase are
* aligned with the erasesize at the appropriate addresses.
*/
......@@ -1155,9 +1143,6 @@ static int cfi_staa_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
if (len & (mtd->erasesize -1))
return -EINVAL;
if ((len + ofs) > mtd->size)
return -EINVAL;
chipnum = ofs >> cfi->chipshift;
adr = ofs - (chipnum << cfi->chipshift);
......
......@@ -173,12 +173,6 @@ int cfi_varsize_frob(struct mtd_info *mtd, varsize_frob_t frob,
int i, first;
struct mtd_erase_region_info *regions = mtd->eraseregions;
if (ofs > mtd->size)
return -EINVAL;
if ((len + ofs) > mtd->size)
return -EINVAL;
/* Check that both start and end of the requested erase are
* aligned with the erasesize at the appropriate addresses.
*/
......
......@@ -101,7 +101,7 @@ static void fixup_use_fwh_lock(struct mtd_info *mtd)
{
printk(KERN_NOTICE "using fwh lock/unlock method\n");
/* Setup for the chips with the fwh lock method */
mtd->lock = fwh_lock_varsize;
mtd->unlock = fwh_unlock_varsize;
mtd->_lock = fwh_lock_varsize;
mtd->_unlock = fwh_unlock_varsize;
}
#endif /* FWH_LOCK_H */
......@@ -55,10 +55,10 @@ static struct mtd_info *map_absent_probe(struct map_info *map)
mtd->name = map->name;
mtd->type = MTD_ABSENT;
mtd->size = map->size;
mtd->erase = map_absent_erase;
mtd->read = map_absent_read;
mtd->write = map_absent_write;
mtd->sync = map_absent_sync;
mtd->_erase = map_absent_erase;
mtd->_read = map_absent_read;
mtd->_write = map_absent_write;
mtd->_sync = map_absent_sync;
mtd->flags = 0;
mtd->erasesize = PAGE_SIZE;
mtd->writesize = 1;
......@@ -70,13 +70,11 @@ static struct mtd_info *map_absent_probe(struct map_info *map)
static int map_absent_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf)
{
*retlen = 0;
return -ENODEV;
}
static int map_absent_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf)
{
*retlen = 0;
return -ENODEV;
}
......
......@@ -64,11 +64,11 @@ static struct mtd_info *map_ram_probe(struct map_info *map)
mtd->name = map->name;
mtd->type = MTD_RAM;
mtd->size = map->size;
mtd->erase = mapram_erase;
mtd->get_unmapped_area = mapram_unmapped_area;
mtd->read = mapram_read;
mtd->write = mapram_write;
mtd->sync = mapram_nop;
mtd->_erase = mapram_erase;
mtd->_get_unmapped_area = mapram_unmapped_area;
mtd->_read = mapram_read;
mtd->_write = mapram_write;
mtd->_sync = mapram_nop;
mtd->flags = MTD_CAP_RAM;
mtd->writesize = 1;
......@@ -122,14 +122,10 @@ static int mapram_erase (struct mtd_info *mtd, struct erase_info *instr)
unsigned long i;
allff = map_word_ff(map);
for (i=0; i<instr->len; i += map_bankwidth(map))
map_write(map, allff, instr->addr + i);
instr->state = MTD_ERASE_DONE;
mtd_erase_callback(instr);
return 0;
}
......
......@@ -41,11 +41,11 @@ static struct mtd_info *map_rom_probe(struct map_info *map)
mtd->name = map->name;
mtd->type = MTD_ROM;
mtd->size = map->size;
mtd->get_unmapped_area = maprom_unmapped_area;
mtd->read = maprom_read;
mtd->write = maprom_write;
mtd->sync = maprom_nop;
mtd->erase = maprom_erase;
mtd->_get_unmapped_area = maprom_unmapped_area;
mtd->_read = maprom_read;
mtd->_write = maprom_write;
mtd->_sync = maprom_nop;
mtd->_erase = maprom_erase;
mtd->flags = MTD_CAP_ROM;
mtd->erasesize = map->size;
mtd->writesize = 1;
......@@ -85,8 +85,7 @@ static void maprom_nop(struct mtd_info *mtd)
static int maprom_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf)
{
printk(KERN_NOTICE "maprom_write called\n");
return -EIO;
return -EROFS;
}
static int maprom_erase (struct mtd_info *mtd, struct erase_info *info)
......
......@@ -103,6 +103,13 @@ config M25PXX_USE_FAST_READ
help
This option enables FAST_READ access supported by ST M25Pxx.
config MTD_SPEAR_SMI
tristate "SPEAR MTD NOR Support through SMI controller"
depends on PLAT_SPEAR
default y
help
This enable SNOR support on SPEAR platforms using SMI controller
config MTD_SST25L
tristate "Support SST25L (non JEDEC) SPI Flash chips"
depends on SPI_MASTER
......
......@@ -17,6 +17,7 @@ obj-$(CONFIG_MTD_LART) += lart.o
obj-$(CONFIG_MTD_BLOCK2MTD) += block2mtd.o
obj-$(CONFIG_MTD_DATAFLASH) += mtd_dataflash.o
obj-$(CONFIG_MTD_M25P80) += m25p80.o
obj-$(CONFIG_MTD_SPEAR_SMI) += spear_smi.o
obj-$(CONFIG_MTD_SST25L) += sst25l.o
CFLAGS_docg3.o += -I$(src)
\ No newline at end of file
......@@ -104,14 +104,6 @@ static int block2mtd_read(struct mtd_info *mtd, loff_t from, size_t len,
int offset = from & (PAGE_SIZE-1);
int cpylen;
if (from > mtd->size)
return -EINVAL;
if (from + len > mtd->size)
len = mtd->size - from;
if (retlen)
*retlen = 0;
while (len) {
if ((offset + len) > PAGE_SIZE)
cpylen = PAGE_SIZE - offset; // multiple pages
......@@ -148,8 +140,6 @@ static int _block2mtd_write(struct block2mtd_dev *dev, const u_char *buf,
int offset = to & ~PAGE_MASK; // page offset
int cpylen;
if (retlen)
*retlen = 0;
while (len) {
if ((offset+len) > PAGE_SIZE)
cpylen = PAGE_SIZE - offset; // multiple pages
......@@ -188,13 +178,6 @@ static int block2mtd_write(struct mtd_info *mtd, loff_t to, size_t len,
struct block2mtd_dev *dev = mtd->priv;
int err;
if (!len)
return 0;
if (to >= mtd->size)
return -ENOSPC;
if (to + len > mtd->size)
len = mtd->size - to;
mutex_lock(&dev->write_mutex);
err = _block2mtd_write(dev, buf, to, len, retlen);
mutex_unlock(&dev->write_mutex);
......@@ -283,13 +266,14 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size)
dev->mtd.size = dev->blkdev->bd_inode->i_size & PAGE_MASK;
dev->mtd.erasesize = erase_size;
dev->mtd.writesize = 1;
dev->mtd.writebufsize = PAGE_SIZE;
dev->mtd.type = MTD_RAM;
dev->mtd.flags = MTD_CAP_RAM;
dev->mtd.erase = block2mtd_erase;
dev->mtd.write = block2mtd_write;
dev->mtd.writev = mtd_writev;
dev->mtd.sync = block2mtd_sync;
dev->mtd.read = block2mtd_read;
dev->mtd._erase = block2mtd_erase;
dev->mtd._write = block2mtd_write;
dev->mtd._writev = mtd_writev;
dev->mtd._sync = block2mtd_sync;
dev->mtd._read = block2mtd_read;
dev->mtd.priv = dev;
dev->mtd.owner = THIS_MODULE;
......
......@@ -562,14 +562,15 @@ void DoC2k_init(struct mtd_info *mtd)
mtd->type = MTD_NANDFLASH;
mtd->flags = MTD_CAP_NANDFLASH;
mtd->writesize = 512;
mtd->writebufsize = mtd->writesize = 512;
mtd->oobsize = 16;
mtd->ecc_strength = 2;
mtd->owner = THIS_MODULE;
mtd->erase = doc_erase;
mtd->read = doc_read;
mtd->write = doc_write;
mtd->read_oob = doc_read_oob;
mtd->write_oob = doc_write_oob;
mtd->_erase = doc_erase;
mtd->_read = doc_read;
mtd->_write = doc_write;
mtd->_read_oob = doc_read_oob;
mtd->_write_oob = doc_write_oob;
this->curfloor = -1;
this->curchip = -1;
mutex_init(&this->lock);
......@@ -602,13 +603,7 @@ static int doc_read(struct mtd_info *mtd, loff_t from, size_t len,
int i, len256 = 0, ret=0;
size_t left = len;
/* Don't allow read past end of device */
if (from >= this->totlen)
return -EINVAL;
mutex_lock(&this->lock);
*retlen = 0;
while (left) {
len = left;
......@@ -748,13 +743,7 @@ static int doc_write(struct mtd_info *mtd, loff_t to, size_t len,
size_t left = len;
int status;
/* Don't allow write past end of device */
if (to >= this->totlen)
return -EINVAL;
mutex_lock(&this->lock);
*retlen = 0;
while (left) {
len = left;
......
......@@ -346,14 +346,15 @@ void DoCMil_init(struct mtd_info *mtd)
/* FIXME: erase size is not always 8KiB */
mtd->erasesize = 0x2000;
mtd->writesize = 512;
mtd->writebufsize = mtd->writesize = 512;
mtd->oobsize = 16;
mtd->ecc_strength = 2;
mtd->owner = THIS_MODULE;
mtd->erase = doc_erase;
mtd->read = doc_read;
mtd->write = doc_write;
mtd->read_oob = doc_read_oob;
mtd->write_oob = doc_write_oob;
mtd->_erase = doc_erase;
mtd->_read = doc_read;
mtd->_write = doc_write;
mtd->_read_oob = doc_read_oob;
mtd->_write_oob = doc_write_oob;
this->curfloor = -1;
this->curchip = -1;
......@@ -383,10 +384,6 @@ static int doc_read (struct mtd_info *mtd, loff_t from, size_t len,
void __iomem *docptr = this->virtadr;
struct Nand *mychip = &this->chips[from >> (this->chipshift)];
/* Don't allow read past end of device */
if (from >= this->totlen)
return -EINVAL;
/* Don't allow a single read to cross a 512-byte block boundary */
if (from + len > ((from | 0x1ff) + 1))
len = ((from | 0x1ff) + 1) - from;
......@@ -494,10 +491,6 @@ static int doc_write (struct mtd_info *mtd, loff_t to, size_t len,
void __iomem *docptr = this->virtadr;
struct Nand *mychip = &this->chips[to >> (this->chipshift)];
/* Don't allow write past end of device */
if (to >= this->totlen)
return -EINVAL;
#if 0
/* Don't allow a single write to cross a 512-byte block boundary */
if (to + len > ( (to | 0x1ff) + 1))
......@@ -599,7 +592,6 @@ static int doc_write (struct mtd_info *mtd, loff_t to, size_t len,
printk("Error programming flash\n");
/* Error in programming
FIXME: implement Bad Block Replacement (in nftl.c ??) */
*retlen = 0;
ret = -EIO;
}
dummy = ReadDOC(docptr, LastDataRead);
......
......@@ -467,14 +467,15 @@ void DoCMilPlus_init(struct mtd_info *mtd)
mtd->type = MTD_NANDFLASH;
mtd->flags = MTD_CAP_NANDFLASH;
mtd->writesize = 512;
mtd->writebufsize = mtd->writesize = 512;
mtd->oobsize = 16;
mtd->ecc_strength = 2;
mtd->owner = THIS_MODULE;
mtd->erase = doc_erase;
mtd->read = doc_read;
mtd->write = doc_write;
mtd->read_oob = doc_read_oob;
mtd->write_oob = doc_write_oob;
mtd->_erase = doc_erase;
mtd->_read = doc_read;
mtd->_write = doc_write;
mtd->_read_oob = doc_read_oob;
mtd->_write_oob = doc_write_oob;
this->curfloor = -1;
this->curchip = -1;
......@@ -581,10 +582,6 @@ static int doc_read(struct mtd_info *mtd, loff_t from, size_t len,
void __iomem * docptr = this->virtadr;
struct Nand *mychip = &this->chips[from >> (this->chipshift)];
/* Don't allow read past end of device */
if (from >= this->totlen)
return -EINVAL;
/* Don't allow a single read to cross a 512-byte block boundary */
if (from + len > ((from | 0x1ff) + 1))
len = ((from | 0x1ff) + 1) - from;
......@@ -700,10 +697,6 @@ static int doc_write(struct mtd_info *mtd, loff_t to, size_t len,
void __iomem * docptr = this->virtadr;
struct Nand *mychip = &this->chips[to >> (this->chipshift)];
/* Don't allow write past end of device */
if (to >= this->totlen)
return -EINVAL;
/* Don't allow writes which aren't exactly one block (512 bytes) */
if ((to & 0x1ff) || (len != 0x200))
return -EINVAL;
......@@ -800,7 +793,6 @@ static int doc_write(struct mtd_info *mtd, loff_t to, size_t len,
printk("MTD: Error 0x%x programming at 0x%x\n", dummy, (int)to);
/* Error in programming
FIXME: implement Bad Block Replacement (in nftl.c ??) */
*retlen = 0;
ret = -EIO;
}
dummy = ReadDOC(docptr, Mplus_LastDataRead);
......
This diff is collapsed.
......@@ -22,6 +22,8 @@
#ifndef _MTD_DOCG3_H
#define _MTD_DOCG3_H
#include <linux/mtd/mtd.h>
/*
* Flash memory areas :
* - 0x0000 .. 0x07ff : IPL
......@@ -266,10 +268,24 @@
*/
#define DOC_LAYOUT_DPS_KEY_LENGTH 8
/**
* struct docg3_cascade - Cascade of 1 to 4 docg3 chips
* @floors: floors (ie. one physical docg3 chip is one floor)
* @base: IO space to access all chips in the cascade
* @bch: the BCH correcting control structure
* @lock: lock to protect docg3 IO space from concurrent accesses
*/
struct docg3_cascade {
struct mtd_info *floors[DOC_MAX_NBFLOORS];
void __iomem *base;
struct bch_control *bch;
struct mutex lock;
};
/**
* struct docg3 - DiskOnChip driver private data
* @dev: the device currently under control
* @base: mapped IO space
* @cascade: the cascade this device belongs to
* @device_id: number of the cascaded DoCG3 device (0, 1, 2 or 3)
* @if_cfg: if true, reads are on 16bits, else reads are on 8bits
......@@ -287,7 +303,7 @@
*/
struct docg3 {
struct device *dev;
void __iomem *base;
struct docg3_cascade *cascade;
unsigned int device_id:4;
unsigned int if_cfg:1;
unsigned int reliable:2;
......
......@@ -367,9 +367,6 @@ static int flash_erase (struct mtd_info *mtd,struct erase_info *instr)
printk (KERN_DEBUG "%s(addr = 0x%.8x, len = %d)\n", __func__, instr->addr, instr->len);
#endif
/* sanity checks */
if (instr->addr + instr->len > mtd->size) return (-EINVAL);
/*
* check that both start and end of the requested erase are
* aligned with the erasesize at the appropriate addresses.
......@@ -440,10 +437,6 @@ static int flash_read (struct mtd_info *mtd,loff_t from,size_t len,size_t *retle
printk (KERN_DEBUG "%s(from = 0x%.8x, len = %d)\n", __func__, (__u32)from, len);
#endif
/* sanity checks */
if (!len) return (0);
if (from + len > mtd->size) return (-EINVAL);
/* we always read len bytes */
*retlen = len;
......@@ -522,11 +515,8 @@ static int flash_write (struct mtd_info *mtd,loff_t to,size_t len,size_t *retlen
printk (KERN_DEBUG "%s(to = 0x%.8x, len = %d)\n", __func__, (__u32)to, len);
#endif
*retlen = 0;
/* sanity checks */
if (!len) return (0);
if (to + len > mtd->size) return (-EINVAL);
/* first, we write a 0xFF.... padded byte until we reach a dword boundary */
if (to & (BUSWIDTH - 1))
......@@ -630,14 +620,15 @@ static int __init lart_flash_init (void)
mtd.name = module_name;
mtd.type = MTD_NORFLASH;
mtd.writesize = 1;
mtd.writebufsize = 4;
mtd.flags = MTD_CAP_NORFLASH;
mtd.size = FLASH_BLOCKSIZE_PARAM * FLASH_NUMBLOCKS_16m_PARAM + FLASH_BLOCKSIZE_MAIN * FLASH_NUMBLOCKS_16m_MAIN;
mtd.erasesize = FLASH_BLOCKSIZE_MAIN;
mtd.numeraseregions = ARRAY_SIZE(erase_regions);
mtd.eraseregions = erase_regions;
mtd.erase = flash_erase;
mtd.read = flash_read;
mtd.write = flash_write;
mtd._erase = flash_erase;
mtd._read = flash_read;
mtd._write = flash_write;
mtd.owner = THIS_MODULE;
#ifdef LART_DEBUG
......
......@@ -288,9 +288,6 @@ static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr)
__func__, (long long)instr->addr,
(long long)instr->len);
/* sanity checks */
if (instr->addr + instr->len > flash->mtd.size)
return -EINVAL;
div_u64_rem(instr->len, mtd->erasesize, &rem);
if (rem)
return -EINVAL;
......@@ -349,13 +346,6 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
pr_debug("%s: %s from 0x%08x, len %zd\n", dev_name(&flash->spi->dev),
__func__, (u32)from, len);
/* sanity checks */
if (!len)
return 0;
if (from + len > flash->mtd.size)
return -EINVAL;
spi_message_init(&m);
memset(t, 0, (sizeof t));
......@@ -371,9 +361,6 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
t[1].len = len;
spi_message_add_tail(&t[1], &m);
/* Byte count starts at zero. */
*retlen = 0;
mutex_lock(&flash->lock);
/* Wait till previous write/erase is done. */
......@@ -417,15 +404,6 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len,
pr_debug("%s: %s to 0x%08x, len %zd\n", dev_name(&flash->spi->dev),
__func__, (u32)to, len);
*retlen = 0;
/* sanity checks */
if (!len)
return(0);
if (to + len > flash->mtd.size)
return -EINVAL;
spi_message_init(&m);
memset(t, 0, (sizeof t));
......@@ -509,15 +487,6 @@ static int sst_write(struct mtd_info *mtd, loff_t to, size_t len,
pr_debug("%s: %s to 0x%08x, len %zd\n", dev_name(&flash->spi->dev),
__func__, (u32)to, len);
*retlen = 0;
/* sanity checks */
if (!len)
return 0;
if (to + len > flash->mtd.size)
return -EINVAL;
spi_message_init(&m);
memset(t, 0, (sizeof t));
......@@ -908,14 +877,14 @@ static int __devinit m25p_probe(struct spi_device *spi)
flash->mtd.writesize = 1;
flash->mtd.flags = MTD_CAP_NORFLASH;
flash->mtd.size = info->sector_size * info->n_sectors;
flash->mtd.erase = m25p80_erase;
flash->mtd.read = m25p80_read;
flash->mtd._erase = m25p80_erase;
flash->mtd._read = m25p80_read;
/* sst flash chips use AAI word program */
if (JEDEC_MFR(info->jedec_id) == CFI_MFR_SST)
flash->mtd.write = sst_write;
flash->mtd._write = sst_write;
else
flash->mtd.write = m25p80_write;
flash->mtd._write = m25p80_write;
/* prefer "small sector" erase if possible */
if (info->flags & SECT_4K) {
......@@ -932,6 +901,7 @@ static int __devinit m25p_probe(struct spi_device *spi)
ppdata.of_node = spi->dev.of_node;
flash->mtd.dev.parent = &spi->dev;
flash->page_size = info->page_size;
flash->mtd.writebufsize = flash->page_size;
if (info->addr_width)
flash->addr_width = info->addr_width;
......@@ -1004,21 +974,7 @@ static struct spi_driver m25p80_driver = {
*/
};
static int __init m25p80_init(void)
{
return spi_register_driver(&m25p80_driver);
}
static void __exit m25p80_exit(void)
{
spi_unregister_driver(&m25p80_driver);
}
module_init(m25p80_init);
module_exit(m25p80_exit);
module_spi_driver(m25p80_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mike Lavender");
......
......@@ -59,12 +59,8 @@ static int ms02nv_read(struct mtd_info *mtd, loff_t from,
{
struct ms02nv_private *mp = mtd->priv;
if (from + len > mtd->size)
return -EINVAL;
memcpy(buf, mp->uaddr + from, len);
*retlen = len;
return 0;
}
......@@ -73,12 +69,8 @@ static int ms02nv_write(struct mtd_info *mtd, loff_t to,
{
struct ms02nv_private *mp = mtd->priv;
if (to + len > mtd->size)
return -EINVAL;
memcpy(mp->uaddr + to, buf, len);
*retlen = len;
return 0;
}
......@@ -215,8 +207,8 @@ static int __init ms02nv_init_one(ulong addr)
mtd->size = fixsize;
mtd->name = (char *)ms02nv_name;
mtd->owner = THIS_MODULE;
mtd->read = ms02nv_read;
mtd->write = ms02nv_write;
mtd->_read = ms02nv_read;
mtd->_write = ms02nv_write;
mtd->writesize = 1;
ret = -EIO;
......
......@@ -164,9 +164,6 @@ static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr)
dev_name(&spi->dev), (long long)instr->addr,
(long long)instr->len);
/* Sanity checks */
if (instr->addr + instr->len > mtd->size)
return -EINVAL;
div_u64_rem(instr->len, priv->page_size, &rem);
if (rem)
return -EINVAL;
......@@ -252,14 +249,6 @@ static int dataflash_read(struct mtd_info *mtd, loff_t from, size_t len,
pr_debug("%s: read 0x%x..0x%x\n", dev_name(&priv->spi->dev),
(unsigned)from, (unsigned)(from + len));
*retlen = 0;
/* Sanity checks */
if (!len)
return 0;
if (from + len > mtd->size)
return -EINVAL;
/* Calculate flash page/byte address */
addr = (((unsigned)from / priv->page_size) << priv->page_offset)
+ ((unsigned)from % priv->page_size);
......@@ -328,14 +317,6 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len,
pr_debug("%s: write 0x%x..0x%x\n",
dev_name(&spi->dev), (unsigned)to, (unsigned)(to + len));
*retlen = 0;
/* Sanity checks */
if (!len)
return 0;
if ((to + len) > mtd->size)
return -EINVAL;
spi_message_init(&msg);
x[0].tx_buf = command = priv->command;
......@@ -490,8 +471,6 @@ static ssize_t otp_read(struct spi_device *spi, unsigned base,
if ((off + len) > 64)
len = 64 - off;
if (len == 0)
return len;
spi_message_init(&m);
......@@ -611,16 +590,16 @@ static int dataflash_write_user_otp(struct mtd_info *mtd,
static char *otp_setup(struct mtd_info *device, char revision)
{
device->get_fact_prot_info = dataflash_get_otp_info;
device->read_fact_prot_reg = dataflash_read_fact_otp;
device->get_user_prot_info = dataflash_get_otp_info;
device->read_user_prot_reg = dataflash_read_user_otp;
device->_get_fact_prot_info = dataflash_get_otp_info;
device->_read_fact_prot_reg = dataflash_read_fact_otp;
device->_get_user_prot_info = dataflash_get_otp_info;
device->_read_user_prot_reg = dataflash_read_user_otp;
/* rev c parts (at45db321c and at45db1281 only!) use a
* different write procedure; not (yet?) implemented.
*/
if (revision > 'c')
device->write_user_prot_reg = dataflash_write_user_otp;
device->_write_user_prot_reg = dataflash_write_user_otp;
return ", OTP";
}
......@@ -672,9 +651,9 @@ add_dataflash_otp(struct spi_device *spi, char *name,
device->owner = THIS_MODULE;
device->type = MTD_DATAFLASH;
device->flags = MTD_WRITEABLE;
device->erase = dataflash_erase;
device->read = dataflash_read;
device->write = dataflash_write;
device->_erase = dataflash_erase;
device->_read = dataflash_read;
device->_write = dataflash_write;
device->priv = priv;
device->dev.parent = &spi->dev;
......@@ -946,18 +925,7 @@ static struct spi_driver dataflash_driver = {
/* FIXME: investigate suspend and resume... */
};
static int __init dataflash_init(void)
{
return spi_register_driver(&dataflash_driver);
}
module_init(dataflash_init);
static void __exit dataflash_exit(void)
{
spi_unregister_driver(&dataflash_driver);
}
module_exit(dataflash_exit);
module_spi_driver(dataflash_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Andrew Victor, David Brownell");
......
......@@ -34,34 +34,23 @@ static struct mtd_info *mtd_info;
static int ram_erase(struct mtd_info *mtd, struct erase_info *instr)
{
if (instr->addr + instr->len > mtd->size)
return -EINVAL;
memset((char *)mtd->priv + instr->addr, 0xff, instr->len);
instr->state = MTD_ERASE_DONE;
mtd_erase_callback(instr);
return 0;
}
static int ram_point(struct mtd_info *mtd, loff_t from, size_t len,
size_t *retlen, void **virt, resource_size_t *phys)
{
if (from + len > mtd->size)
return -EINVAL;
/* can we return a physical address with this driver? */
if (phys)
return -EINVAL;
*virt = mtd->priv + from;
*retlen = len;
return 0;
}
static void ram_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
static int ram_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
{
return 0;
}
/*
......@@ -80,11 +69,7 @@ static unsigned long ram_get_unmapped_area(struct mtd_info *mtd,
static int ram_read(struct mtd_info *mtd, loff_t from, size_t len,
size_t *retlen, u_char *buf)
{
if (from + len > mtd->size)
return -EINVAL;
memcpy(buf, mtd->priv + from, len);
*retlen = len;
return 0;
}
......@@ -92,11 +77,7 @@ static int ram_read(struct mtd_info *mtd, loff_t from, size_t len,
static int ram_write(struct mtd_info *mtd, loff_t to, size_t len,
size_t *retlen, const u_char *buf)
{
if (to + len > mtd->size)
return -EINVAL;
memcpy((char *)mtd->priv + to, buf, len);
*retlen = len;
return 0;
}
......@@ -126,12 +107,12 @@ int mtdram_init_device(struct mtd_info *mtd, void *mapped_address,
mtd->priv = mapped_address;
mtd->owner = THIS_MODULE;
mtd->erase = ram_erase;
mtd->point = ram_point;
mtd->unpoint = ram_unpoint;
mtd->get_unmapped_area = ram_get_unmapped_area;
mtd->read = ram_read;
mtd->write = ram_write;
mtd->_erase = ram_erase;
mtd->_point = ram_point;
mtd->_unpoint = ram_unpoint;
mtd->_get_unmapped_area = ram_get_unmapped_area;
mtd->_read = ram_read;
mtd->_write = ram_write;
if (mtd_device_register(mtd, NULL, 0))
return -EIO;
......
......@@ -33,45 +33,33 @@ struct phram_mtd_list {
static LIST_HEAD(phram_list);
static int phram_erase(struct mtd_info *mtd, struct erase_info *instr)
{
u_char *start = mtd->priv;
if (instr->addr + instr->len > mtd->size)
return -EINVAL;
memset(start + instr->addr, 0xff, instr->len);
/* This'll catch a few races. Free the thing before returning :)
/*
* This'll catch a few races. Free the thing before returning :)
* I don't feel at all ashamed. This kind of thing is possible anyway
* with flash, but unlikely.
*/
instr->state = MTD_ERASE_DONE;
mtd_erase_callback(instr);
return 0;
}
static int phram_point(struct mtd_info *mtd, loff_t from, size_t len,
size_t *retlen, void **virt, resource_size_t *phys)
{
if (from + len > mtd->size)
return -EINVAL;
/* can we return a physical address with this driver? */
if (phys)
return -EINVAL;
*virt = mtd->priv + from;
*retlen = len;
return 0;
}
static void phram_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
static int phram_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
{
return 0;
}
static int phram_read(struct mtd_info *mtd, loff_t from, size_t len,
......@@ -79,14 +67,7 @@ static int phram_read(struct mtd_info *mtd, loff_t from, size_t len,
{
u_char *start = mtd->priv;
if (from >= mtd->size)
return -EINVAL;
if (len > mtd->size - from)
len = mtd->size - from;
memcpy(buf, start + from, len);
*retlen = len;
return 0;
}
......@@ -96,20 +77,11 @@ static int phram_write(struct mtd_info *mtd, loff_t to, size_t len,
{
u_char *start = mtd->priv;
if (to >= mtd->size)
return -EINVAL;
if (len > mtd->size - to)
len = mtd->size - to;
memcpy(start + to, buf, len);
*retlen = len;
return 0;
}
static void unregister_devices(void)
{
struct phram_mtd_list *this, *safe;
......@@ -142,11 +114,11 @@ static int register_device(char *name, unsigned long start, unsigned long len)
new->mtd.name = name;
new->mtd.size = len;
new->mtd.flags = MTD_CAP_RAM;
new->mtd.erase = phram_erase;
new->mtd.point = phram_point;
new->mtd.unpoint = phram_unpoint;
new->mtd.read = phram_read;
new->mtd.write = phram_write;
new->mtd._erase = phram_erase;
new->mtd._point = phram_point;
new->mtd._unpoint = phram_unpoint;
new->mtd._read = phram_read;
new->mtd._write = phram_write;
new->mtd.owner = THIS_MODULE;
new->mtd.type = MTD_RAM;
new->mtd.erasesize = PAGE_SIZE;
......@@ -233,7 +205,17 @@ static inline void kill_final_newline(char *str)
return 1; \
} while (0)
static int phram_setup(const char *val, struct kernel_param *kp)
/*
* This shall contain the module parameter if any. It is of the form:
* - phram=<device>,<address>,<size> for module case
* - phram.phram=<device>,<address>,<size> for built-in case
* We leave 64 bytes for the device name, 12 for the address and 12 for the
* size.
* Example: phram.phram=rootfs,0xa0000000,512Mi
*/
static __initdata char phram_paramline[64+12+12];
static int __init phram_setup(const char *val)
{
char buf[64+12+12], *str = buf;
char *token[3];
......@@ -282,12 +264,28 @@ static int phram_setup(const char *val, struct kernel_param *kp)
return ret;
}
module_param_call(phram, phram_setup, NULL, NULL, 000);
static int __init phram_param_call(const char *val, struct kernel_param *kp)
{
/*
* This function is always called before 'init_phram()', whether
* built-in or module.
*/
if (strlen(val) >= sizeof(phram_paramline))
return -ENOSPC;
strcpy(phram_paramline, val);
return 0;
}
module_param_call(phram, phram_param_call, NULL, NULL, 000);
MODULE_PARM_DESC(phram, "Memory region to map. \"phram=<name>,<start>,<length>\"");
static int __init init_phram(void)
{
if (phram_paramline[0])
return phram_setup(phram_paramline);
return 0;
}
......
......@@ -94,12 +94,48 @@
#include <linux/ioctl.h>
#include <asm/io.h>
#include <linux/pci.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/pmc551.h>
#define PMC551_VERSION \
"Ramix PMC551 PCI Mezzanine Ram Driver. (C) 1999,2000 Nortel Networks.\n"
#define PCI_VENDOR_ID_V3_SEMI 0x11b0
#define PCI_DEVICE_ID_V3_SEMI_V370PDC 0x0200
#define PMC551_PCI_MEM_MAP0 0x50
#define PMC551_PCI_MEM_MAP1 0x54
#define PMC551_PCI_MEM_MAP_MAP_ADDR_MASK 0x3ff00000
#define PMC551_PCI_MEM_MAP_APERTURE_MASK 0x000000f0
#define PMC551_PCI_MEM_MAP_REG_EN 0x00000002
#define PMC551_PCI_MEM_MAP_ENABLE 0x00000001
#define PMC551_SDRAM_MA 0x60
#define PMC551_SDRAM_CMD 0x62
#define PMC551_DRAM_CFG 0x64
#define PMC551_SYS_CTRL_REG 0x78
#define PMC551_DRAM_BLK0 0x68
#define PMC551_DRAM_BLK1 0x6c
#define PMC551_DRAM_BLK2 0x70
#define PMC551_DRAM_BLK3 0x74
#define PMC551_DRAM_BLK_GET_SIZE(x) (524288 << ((x >> 4) & 0x0f))
#define PMC551_DRAM_BLK_SET_COL_MUX(x, v) (((x) & ~0x00007000) | (((v) & 0x7) << 12))
#define PMC551_DRAM_BLK_SET_ROW_MUX(x, v) (((x) & ~0x00000f00) | (((v) & 0xf) << 8))
struct mypriv {
struct pci_dev *dev;
u_char *start;
u32 base_map0;
u32 curr_map0;
u32 asize;
struct mtd_info *nextpmc551;
};
static struct mtd_info *pmc551list;
static int pmc551_point(struct mtd_info *mtd, loff_t from, size_t len,
size_t *retlen, void **virt, resource_size_t *phys);
static int pmc551_erase(struct mtd_info *mtd, struct erase_info *instr)
{
struct mypriv *priv = mtd->priv;
......@@ -115,16 +151,6 @@ static int pmc551_erase(struct mtd_info *mtd, struct erase_info *instr)
#endif
end = instr->addr + instr->len - 1;
/* Is it past the end? */
if (end > mtd->size) {
#ifdef CONFIG_MTD_PMC551_DEBUG
printk(KERN_DEBUG "pmc551_erase() out of bounds (%ld > %ld)\n",
(long)end, (long)mtd->size);
#endif
return -EINVAL;
}
eoff_hi = end & ~(priv->asize - 1);
soff_hi = instr->addr & ~(priv->asize - 1);
eoff_lo = end & (priv->asize - 1);
......@@ -178,18 +204,6 @@ static int pmc551_point(struct mtd_info *mtd, loff_t from, size_t len,
printk(KERN_DEBUG "pmc551_point(%ld, %ld)\n", (long)from, (long)len);
#endif
if (from + len > mtd->size) {
#ifdef CONFIG_MTD_PMC551_DEBUG
printk(KERN_DEBUG "pmc551_point() out of bounds (%ld > %ld)\n",
(long)from + len, (long)mtd->size);
#endif
return -EINVAL;
}
/* can we return a physical address with this driver? */
if (phys)
return -EINVAL;
soff_hi = from & ~(priv->asize - 1);
soff_lo = from & (priv->asize - 1);
......@@ -205,11 +219,12 @@ static int pmc551_point(struct mtd_info *mtd, loff_t from, size_t len,
return 0;
}
static void pmc551_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
static int pmc551_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
{
#ifdef CONFIG_MTD_PMC551_DEBUG
printk(KERN_DEBUG "pmc551_unpoint()\n");
#endif
return 0;
}
static int pmc551_read(struct mtd_info *mtd, loff_t from, size_t len,
......@@ -228,16 +243,6 @@ static int pmc551_read(struct mtd_info *mtd, loff_t from, size_t len,
#endif
end = from + len - 1;
/* Is it past the end? */
if (end > mtd->size) {
#ifdef CONFIG_MTD_PMC551_DEBUG
printk(KERN_DEBUG "pmc551_read() out of bounds (%ld > %ld)\n",
(long)end, (long)mtd->size);
#endif
return -EINVAL;
}
soff_hi = from & ~(priv->asize - 1);
eoff_hi = end & ~(priv->asize - 1);
soff_lo = from & (priv->asize - 1);
......@@ -295,16 +300,6 @@ static int pmc551_write(struct mtd_info *mtd, loff_t to, size_t len,
#endif
end = to + len - 1;
/* Is it past the end? or did the u32 wrap? */
if (end > mtd->size) {
#ifdef CONFIG_MTD_PMC551_DEBUG
printk(KERN_DEBUG "pmc551_write() out of bounds (end: %ld, "
"size: %ld, to: %ld)\n", (long)end, (long)mtd->size,
(long)to);
#endif
return -EINVAL;
}
soff_hi = to & ~(priv->asize - 1);
eoff_hi = end & ~(priv->asize - 1);
soff_lo = to & (priv->asize - 1);
......@@ -358,7 +353,7 @@ static int pmc551_write(struct mtd_info *mtd, loff_t to, size_t len,
* mechanism
* returns the size of the memory region found.
*/
static u32 fixup_pmc551(struct pci_dev *dev)
static int fixup_pmc551(struct pci_dev *dev)
{
#ifdef CONFIG_MTD_PMC551_BUGFIX
u32 dram_data;
......@@ -668,7 +663,7 @@ static int __init init_pmc551(void)
struct mypriv *priv;
int found = 0;
struct mtd_info *mtd;
u32 length = 0;
int length = 0;
if (msize) {
msize = (1 << (ffs(msize) - 1)) << 20;
......@@ -786,11 +781,11 @@ static int __init init_pmc551(void)
mtd->size = msize;
mtd->flags = MTD_CAP_RAM;
mtd->erase = pmc551_erase;
mtd->read = pmc551_read;
mtd->write = pmc551_write;
mtd->point = pmc551_point;
mtd->unpoint = pmc551_unpoint;
mtd->_erase = pmc551_erase;
mtd->_read = pmc551_read;
mtd->_write = pmc551_write;
mtd->_point = pmc551_point;
mtd->_unpoint = pmc551_unpoint;
mtd->type = MTD_RAM;
mtd->name = "PMC551 RAM board";
mtd->erasesize = 0x10000;
......
......@@ -75,7 +75,7 @@ static slram_mtd_list_t *slram_mtdlist = NULL;
static int slram_erase(struct mtd_info *, struct erase_info *);
static int slram_point(struct mtd_info *, loff_t, size_t, size_t *, void **,
resource_size_t *);
static void slram_unpoint(struct mtd_info *, loff_t, size_t);
static int slram_unpoint(struct mtd_info *, loff_t, size_t);
static int slram_read(struct mtd_info *, loff_t, size_t, size_t *, u_char *);
static int slram_write(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
......@@ -83,21 +83,13 @@ static int slram_erase(struct mtd_info *mtd, struct erase_info *instr)
{
slram_priv_t *priv = mtd->priv;
if (instr->addr + instr->len > mtd->size) {
return(-EINVAL);
}
memset(priv->start + instr->addr, 0xff, instr->len);
/* This'll catch a few races. Free the thing before returning :)
* I don't feel at all ashamed. This kind of thing is possible anyway
* with flash, but unlikely.
*/
instr->state = MTD_ERASE_DONE;
mtd_erase_callback(instr);
return(0);
}
......@@ -106,20 +98,14 @@ static int slram_point(struct mtd_info *mtd, loff_t from, size_t len,
{
slram_priv_t *priv = mtd->priv;
/* can we return a physical address with this driver? */
if (phys)
return -EINVAL;
if (from + len > mtd->size)
return -EINVAL;
*virt = priv->start + from;
*retlen = len;
return(0);
}
static void slram_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
static int slram_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
{
return 0;
}
static int slram_read(struct mtd_info *mtd, loff_t from, size_t len,
......@@ -127,14 +113,7 @@ static int slram_read(struct mtd_info *mtd, loff_t from, size_t len,
{
slram_priv_t *priv = mtd->priv;
if (from > mtd->size)
return -EINVAL;
if (from + len > mtd->size)
len = mtd->size - from;
memcpy(buf, priv->start + from, len);
*retlen = len;
return(0);
}
......@@ -144,11 +123,7 @@ static int slram_write(struct mtd_info *mtd, loff_t to, size_t len,
{
slram_priv_t *priv = mtd->priv;
if (to + len > mtd->size)
return -EINVAL;
memcpy(priv->start + to, buf, len);
*retlen = len;
return(0);
}
......@@ -199,11 +174,11 @@ static int register_device(char *name, unsigned long start, unsigned long length
(*curmtd)->mtdinfo->name = name;
(*curmtd)->mtdinfo->size = length;
(*curmtd)->mtdinfo->flags = MTD_CAP_RAM;
(*curmtd)->mtdinfo->erase = slram_erase;
(*curmtd)->mtdinfo->point = slram_point;
(*curmtd)->mtdinfo->unpoint = slram_unpoint;
(*curmtd)->mtdinfo->read = slram_read;
(*curmtd)->mtdinfo->write = slram_write;
(*curmtd)->mtdinfo->_erase = slram_erase;
(*curmtd)->mtdinfo->_point = slram_point;
(*curmtd)->mtdinfo->_unpoint = slram_unpoint;
(*curmtd)->mtdinfo->_read = slram_read;
(*curmtd)->mtdinfo->_write = slram_write;
(*curmtd)->mtdinfo->owner = THIS_MODULE;
(*curmtd)->mtdinfo->type = MTD_RAM;
(*curmtd)->mtdinfo->erasesize = SLRAM_BLK_SZ;
......
This diff is collapsed.
......@@ -175,9 +175,6 @@ static int sst25l_erase(struct mtd_info *mtd, struct erase_info *instr)
int err;
/* Sanity checks */
if (instr->addr + instr->len > flash->mtd.size)
return -EINVAL;
if ((uint32_t)instr->len % mtd->erasesize)
return -EINVAL;
......@@ -223,16 +220,6 @@ static int sst25l_read(struct mtd_info *mtd, loff_t from, size_t len,
unsigned char command[4];
int ret;
/* Sanity checking */
if (len == 0)
return 0;
if (from + len > flash->mtd.size)
return -EINVAL;
if (retlen)
*retlen = 0;
spi_message_init(&message);
memset(&transfer, 0, sizeof(transfer));
......@@ -274,13 +261,6 @@ static int sst25l_write(struct mtd_info *mtd, loff_t to, size_t len,
int i, j, ret, bytes, copied = 0;
unsigned char command[5];
/* Sanity checks */
if (!len)
return 0;
if (to + len > flash->mtd.size)
return -EINVAL;
if ((uint32_t)to % mtd->writesize)
return -EINVAL;
......@@ -402,10 +382,11 @@ static int __devinit sst25l_probe(struct spi_device *spi)
flash->mtd.flags = MTD_CAP_NORFLASH;
flash->mtd.erasesize = flash_info->erase_size;
flash->mtd.writesize = flash_info->page_size;
flash->mtd.writebufsize = flash_info->page_size;
flash->mtd.size = flash_info->page_size * flash_info->nr_pages;
flash->mtd.erase = sst25l_erase;
flash->mtd.read = sst25l_read;
flash->mtd.write = sst25l_write;
flash->mtd._erase = sst25l_erase;
flash->mtd._read = sst25l_read;
flash->mtd._write = sst25l_write;
dev_info(&spi->dev, "%s (%lld KiB)\n", flash_info->name,
(long long)flash->mtd.size >> 10);
......@@ -418,9 +399,9 @@ static int __devinit sst25l_probe(struct spi_device *spi)
flash->mtd.numeraseregions);
ret = mtd_device_parse_register(&flash->mtd, NULL, 0,
data ? data->parts : NULL,
data ? data->nr_parts : 0);
ret = mtd_device_parse_register(&flash->mtd, NULL, NULL,
data ? data->parts : NULL,
data ? data->nr_parts : 0);
if (ret) {
kfree(flash);
dev_set_drvdata(&spi->dev, NULL);
......@@ -450,18 +431,7 @@ static struct spi_driver sst25l_driver = {
.remove = __devexit_p(sst25l_remove),
};
static int __init sst25l_init(void)
{
return spi_register_driver(&sst25l_driver);
}
static void __exit sst25l_exit(void)
{
spi_unregister_driver(&sst25l_driver);
}
module_init(sst25l_init);
module_exit(sst25l_exit);
module_spi_driver(sst25l_driver);
MODULE_DESCRIPTION("MTD SPI driver for SST25L Flash chips");
MODULE_AUTHOR("Andre Renaud <andre@bluewatersys.com>, "
......
......@@ -56,7 +56,7 @@ static void inftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
if (memcmp(mtd->name, "DiskOnChip", 10))
return;
if (!mtd->block_isbad) {
if (!mtd->_block_isbad) {
printk(KERN_ERR
"INFTL no longer supports the old DiskOnChip drivers loaded via docprobe.\n"
"Please use the new diskonchip driver under the NAND subsystem.\n");
......
......@@ -40,7 +40,7 @@ static int lpddr_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
static int lpddr_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
static int lpddr_point(struct mtd_info *mtd, loff_t adr, size_t len,
size_t *retlen, void **mtdbuf, resource_size_t *phys);
static void lpddr_unpoint(struct mtd_info *mtd, loff_t adr, size_t len);
static int lpddr_unpoint(struct mtd_info *mtd, loff_t adr, size_t len);
static int get_chip(struct map_info *map, struct flchip *chip, int mode);
static int chip_ready(struct map_info *map, struct flchip *chip, int mode);
static void put_chip(struct map_info *map, struct flchip *chip);
......@@ -63,18 +63,18 @@ struct mtd_info *lpddr_cmdset(struct map_info *map)
mtd->type = MTD_NORFLASH;
/* Fill in the default mtd operations */
mtd->read = lpddr_read;
mtd->_read = lpddr_read;
mtd->type = MTD_NORFLASH;
mtd->flags = MTD_CAP_NORFLASH;
mtd->flags &= ~MTD_BIT_WRITEABLE;
mtd->erase = lpddr_erase;
mtd->write = lpddr_write_buffers;
mtd->writev = lpddr_writev;
mtd->lock = lpddr_lock;
mtd->unlock = lpddr_unlock;
mtd->_erase = lpddr_erase;
mtd->_write = lpddr_write_buffers;
mtd->_writev = lpddr_writev;
mtd->_lock = lpddr_lock;
mtd->_unlock = lpddr_unlock;
if (map_is_linear(map)) {
mtd->point = lpddr_point;
mtd->unpoint = lpddr_unpoint;
mtd->_point = lpddr_point;
mtd->_unpoint = lpddr_unpoint;
}
mtd->size = 1 << lpddr->qinfo->DevSizeShift;
mtd->erasesize = 1 << lpddr->qinfo->UniformBlockSizeShift;
......@@ -530,14 +530,12 @@ static int lpddr_point(struct mtd_info *mtd, loff_t adr, size_t len,
struct flchip *chip = &lpddr->chips[chipnum];
int ret = 0;
if (!map->virt || (adr + len > mtd->size))
if (!map->virt)
return -EINVAL;
/* ofs: offset within the first chip that the first read should start */
ofs = adr - (chipnum << lpddr->chipshift);
*mtdbuf = (void *)map->virt + chip->start + ofs;
*retlen = 0;
while (len) {
unsigned long thislen;
......@@ -575,11 +573,11 @@ static int lpddr_point(struct mtd_info *mtd, loff_t adr, size_t len,
return 0;
}
static void lpddr_unpoint (struct mtd_info *mtd, loff_t adr, size_t len)
static int lpddr_unpoint (struct mtd_info *mtd, loff_t adr, size_t len)
{
struct map_info *map = mtd->priv;
struct lpddr_private *lpddr = map->fldrv_priv;
int chipnum = adr >> lpddr->chipshift;
int chipnum = adr >> lpddr->chipshift, err = 0;
unsigned long ofs;
/* ofs: offset within the first chip that the first read should start */
......@@ -603,9 +601,11 @@ static void lpddr_unpoint (struct mtd_info *mtd, loff_t adr, size_t len)
chip->ref_point_counter--;
if (chip->ref_point_counter == 0)
chip->state = FL_READY;
} else
} else {
printk(KERN_WARNING "%s: Warning: unpoint called on non"
"pointed region\n", map->name);
err = -EINVAL;
}
put_chip(map, chip);
mutex_unlock(&chip->mutex);
......@@ -614,6 +614,8 @@ static void lpddr_unpoint (struct mtd_info *mtd, loff_t adr, size_t len)
ofs = 0;
chipnum++;
}
return err;
}
static int lpddr_write_buffers(struct mtd_info *mtd, loff_t to, size_t len,
......@@ -637,13 +639,11 @@ static int lpddr_writev(struct mtd_info *mtd, const struct kvec *vecs,
int chipnum;
unsigned long ofs, vec_seek, i;
int wbufsize = 1 << lpddr->qinfo->BufSizeShift;
size_t len = 0;
for (i = 0; i < count; i++)
len += vecs[i].iov_len;
*retlen = 0;
if (!len)
return 0;
......@@ -688,9 +688,6 @@ static int lpddr_erase(struct mtd_info *mtd, struct erase_info *instr)
ofs = instr->addr;
len = instr->len;
if (ofs > mtd->size || (len + ofs) > mtd->size)
return -EINVAL;
while (len > 0) {
ret = do_erase_oneblock(mtd, ofs);
if (ret)
......
......@@ -164,8 +164,8 @@ static int __devinit bfin_flash_probe(struct platform_device *pdev)
return -ENXIO;
}
mtd_device_parse_register(state->mtd, part_probe_types, 0,
pdata->parts, pdata->nr_parts);
mtd_device_parse_register(state->mtd, part_probe_types, NULL,
pdata->parts, pdata->nr_parts);
platform_set_drvdata(pdev, state);
......
......@@ -196,7 +196,7 @@ static int __init init_dc21285(void)
dc21285_mtd->owner = THIS_MODULE;
mtd_device_parse_register(dc21285_mtd, probes, 0, NULL, 0);
mtd_device_parse_register(dc21285_mtd, probes, NULL, NULL, 0);
if(machine_is_ebsa285()) {
/*
......
......@@ -252,8 +252,8 @@ static int __devinit gpio_flash_probe(struct platform_device *pdev)
}
mtd_device_parse_register(state->mtd, part_probe_types, 0,
pdata->parts, pdata->nr_parts);
mtd_device_parse_register(state->mtd, part_probe_types, NULL,
pdata->parts, pdata->nr_parts);
return 0;
}
......
......@@ -85,8 +85,8 @@ static int __init h720x_mtd_init(void)
if (mymtd) {
mymtd->owner = THIS_MODULE;
mtd_device_parse_register(mymtd, NULL, 0,
h720x_partitions, NUM_PARTITIONS);
mtd_device_parse_register(mymtd, NULL, NULL,
h720x_partitions, NUM_PARTITIONS);
return 0;
}
......
......@@ -91,7 +91,7 @@ static int __init init_impa7(void)
if (impa7_mtd[i]) {
impa7_mtd[i]->owner = THIS_MODULE;
devicesfound++;
mtd_device_parse_register(impa7_mtd[i], NULL, 0,
mtd_device_parse_register(impa7_mtd[i], NULL, NULL,
partitions,
ARRAY_SIZE(partitions));
}
......
......@@ -72,7 +72,7 @@ static int __devinit vr_nor_init_partitions(struct vr_nor_mtd *p)
{
/* register the flash bank */
/* partition the flash bank */
return mtd_device_parse_register(p->info, NULL, 0, NULL, 0);
return mtd_device_parse_register(p->info, NULL, NULL, NULL, 0);
}
static void __devexit vr_nor_destroy_mtd_setup(struct vr_nor_mtd *p)
......
......@@ -226,7 +226,7 @@ static int ixp2000_flash_probe(struct platform_device *dev)
}
info->mtd->owner = THIS_MODULE;
err = mtd_device_parse_register(info->mtd, probes, 0, NULL, 0);
err = mtd_device_parse_register(info->mtd, probes, NULL, NULL, 0);
if (err)
goto Error;
......
......@@ -182,6 +182,9 @@ static int ixp4xx_flash_probe(struct platform_device *dev)
{
struct flash_platform_data *plat = dev->dev.platform_data;
struct ixp4xx_flash_info *info;
struct mtd_part_parser_data ppdata = {
.origin = dev->resource->start,
};
int err = -1;
if (!plat)
......@@ -247,7 +250,7 @@ static int ixp4xx_flash_probe(struct platform_device *dev)
/* Use the fast version */
info->map.write = ixp4xx_write16;
err = mtd_device_parse_register(info->mtd, probes, dev->resource->start,
err = mtd_device_parse_register(info->mtd, probes, &ppdata,
plat->parts, plat->nr_parts);
if (err) {
printk(KERN_ERR "Could not parse partitions\n");
......
......@@ -27,17 +27,21 @@ static struct mtd_info *mymtd;
/* Is this really the vpp port? */
static DEFINE_SPINLOCK(l440gx_vpp_lock);
static int l440gx_vpp_refcnt;
static void l440gx_set_vpp(struct map_info *map, int vpp)
{
unsigned long l;
unsigned long flags;
l = inl(VPP_PORT);
spin_lock_irqsave(&l440gx_vpp_lock, flags);
if (vpp) {
l |= 1;
if (++l440gx_vpp_refcnt == 1) /* first nested 'on' */
outl(inl(VPP_PORT) | 1, VPP_PORT);
} else {
l &= ~1;
if (--l440gx_vpp_refcnt == 0) /* last nested 'off' */
outl(inl(VPP_PORT) & ~1, VPP_PORT);
}
outl(l, VPP_PORT);
spin_unlock_irqrestore(&l440gx_vpp_lock, flags);
}
static struct map_info l440gx_map = {
......
......@@ -45,6 +45,7 @@ struct ltq_mtd {
};
static char ltq_map_name[] = "ltq_nor";
static const char *ltq_probe_types[] __devinitconst = { "cmdlinepart", NULL };
static map_word
ltq_read16(struct map_info *map, unsigned long adr)
......@@ -168,8 +169,9 @@ ltq_mtd_probe(struct platform_device *pdev)
cfi->addr_unlock1 ^= 1;
cfi->addr_unlock2 ^= 1;
err = mtd_device_parse_register(ltq_mtd->mtd, NULL, 0,
ltq_mtd_data->parts, ltq_mtd_data->nr_parts);
err = mtd_device_parse_register(ltq_mtd->mtd, ltq_probe_types, NULL,
ltq_mtd_data->parts,
ltq_mtd_data->nr_parts);
if (err) {
dev_err(&pdev->dev, "failed to add partitions\n");
goto err_destroy;
......
......@@ -199,8 +199,9 @@ static int __devinit latch_addr_flash_probe(struct platform_device *dev)
}
info->mtd->owner = THIS_MODULE;
mtd_device_parse_register(info->mtd, NULL, 0,
latch_addr_data->parts, latch_addr_data->nr_parts);
mtd_device_parse_register(info->mtd, NULL, NULL,
latch_addr_data->parts,
latch_addr_data->nr_parts);
return 0;
iounmap:
......
......@@ -294,13 +294,24 @@ static void pcmcia_copy_to(struct map_info *map, unsigned long to, const void *f
}
static DEFINE_SPINLOCK(pcmcia_vpp_lock);
static int pcmcia_vpp_refcnt;
static void pcmciamtd_set_vpp(struct map_info *map, int on)
{
struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1;
struct pcmcia_device *link = dev->p_dev;
unsigned long flags;
pr_debug("dev = %p on = %d vpp = %d\n\n", dev, on, dev->vpp);
pcmcia_fixup_vpp(link, on ? dev->vpp : 0);
spin_lock_irqsave(&pcmcia_vpp_lock, flags);
if (on) {
if (++pcmcia_vpp_refcnt == 1) /* first nested 'on' */
pcmcia_fixup_vpp(link, dev->vpp);
} else {
if (--pcmcia_vpp_refcnt == 0) /* last nested 'off' */
pcmcia_fixup_vpp(link, 0);
}
spin_unlock_irqrestore(&pcmcia_vpp_lock, flags);
}
......
......@@ -27,6 +27,8 @@ struct physmap_flash_info {
struct mtd_info *mtd[MAX_RESOURCES];
struct mtd_info *cmtd;
struct map_info map[MAX_RESOURCES];
spinlock_t vpp_lock;
int vpp_refcnt;
};
static int physmap_flash_remove(struct platform_device *dev)
......@@ -63,12 +65,26 @@ static void physmap_set_vpp(struct map_info *map, int state)
{
struct platform_device *pdev;
struct physmap_flash_data *physmap_data;
struct physmap_flash_info *info;
unsigned long flags;
pdev = (struct platform_device *)map->map_priv_1;
physmap_data = pdev->dev.platform_data;
if (physmap_data->set_vpp)
physmap_data->set_vpp(pdev, state);
if (!physmap_data->set_vpp)
return;
info = platform_get_drvdata(pdev);
spin_lock_irqsave(&info->vpp_lock, flags);
if (state) {
if (++info->vpp_refcnt == 1) /* first nested 'on' */
physmap_data->set_vpp(pdev, 1);
} else {
if (--info->vpp_refcnt == 0) /* last nested 'off' */
physmap_data->set_vpp(pdev, 0);
}
spin_unlock_irqrestore(&info->vpp_lock, flags);
}
static const char *rom_probe_types[] = {
......@@ -172,9 +188,11 @@ static int physmap_flash_probe(struct platform_device *dev)
if (err)
goto err_out;
spin_lock_init(&info->vpp_lock);
part_types = physmap_data->part_probe_types ? : part_probe_types;
mtd_device_parse_register(info->cmtd, part_types, 0,
mtd_device_parse_register(info->cmtd, part_types, NULL,
physmap_data->parts, physmap_data->nr_parts);
return 0;
......
......@@ -222,8 +222,9 @@ static int platram_probe(struct platform_device *pdev)
/* check to see if there are any available partitions, or wether
* to add this device whole */
err = mtd_device_parse_register(info->mtd, pdata->probes, 0,
pdata->partitions, pdata->nr_partitions);
err = mtd_device_parse_register(info->mtd, pdata->probes, NULL,
pdata->partitions,
pdata->nr_partitions);
if (!err)
dev_info(&pdev->dev, "registered mtd device\n");
......
......@@ -98,7 +98,8 @@ static int __devinit pxa2xx_flash_probe(struct platform_device *pdev)
}
info->mtd->owner = THIS_MODULE;
mtd_device_parse_register(info->mtd, probes, 0, flash->parts, flash->nr_parts);
mtd_device_parse_register(info->mtd, probes, NULL, flash->parts,
flash->nr_parts);
platform_set_drvdata(pdev, info);
return 0;
......
......@@ -102,8 +102,8 @@ static int rbtx4939_flash_probe(struct platform_device *dev)
info->mtd->owner = THIS_MODULE;
if (err)
goto err_out;
err = mtd_device_parse_register(info->mtd, NULL, 0,
pdata->parts, pdata->nr_parts);
err = mtd_device_parse_register(info->mtd, NULL, NULL, pdata->parts,
pdata->nr_parts);
if (err)
goto err_out;
......
......@@ -36,10 +36,22 @@ struct sa_info {
struct sa_subdev_info subdev[0];
};
static DEFINE_SPINLOCK(sa1100_vpp_lock);
static int sa1100_vpp_refcnt;
static void sa1100_set_vpp(struct map_info *map, int on)
{
struct sa_subdev_info *subdev = container_of(map, struct sa_subdev_info, map);
subdev->plat->set_vpp(on);
unsigned long flags;
spin_lock_irqsave(&sa1100_vpp_lock, flags);
if (on) {
if (++sa1100_vpp_refcnt == 1) /* first nested 'on' */
subdev->plat->set_vpp(1);
} else {
if (--sa1100_vpp_refcnt == 0) /* last nested 'off' */
subdev->plat->set_vpp(0);
}
spin_unlock_irqrestore(&sa1100_vpp_lock, flags);
}
static void sa1100_destroy_subdev(struct sa_subdev_info *subdev)
......@@ -252,8 +264,8 @@ static int __devinit sa1100_mtd_probe(struct platform_device *pdev)
/*
* Partition selection stuff.
*/
mtd_device_parse_register(info->mtd, part_probes, 0,
plat->parts, plat->nr_parts);
mtd_device_parse_register(info->mtd, part_probes, NULL, plat->parts,
plat->nr_parts);
platform_set_drvdata(pdev, info);
err = 0;
......
......@@ -92,8 +92,8 @@ static int __init init_soleng_maps(void)
mtd_device_register(eprom_mtd, NULL, 0);
}
mtd_device_parse_register(flash_mtd, probes, 0,
superh_se_partitions, NUM_PARTITIONS);
mtd_device_parse_register(flash_mtd, probes, NULL,
superh_se_partitions, NUM_PARTITIONS);
return 0;
}
......
......@@ -85,7 +85,7 @@ static int __init uclinux_mtd_init(void)
}
mtd->owner = THIS_MODULE;
mtd->point = uclinux_point;
mtd->_point = uclinux_point;
mtd->priv = mapp;
uclinux_ram_mtdinfo = mtd;
......
......@@ -360,9 +360,6 @@ static int vmu_flash_read(struct mtd_info *mtd, loff_t from, size_t len,
int index = 0, retval, partition, leftover, numblocks;
unsigned char cx;
if (len < 1)
return -EIO;
mpart = mtd->priv;
mdev = mpart->mdev;
partition = mpart->partition;
......@@ -434,11 +431,6 @@ static int vmu_flash_write(struct mtd_info *mtd, loff_t to, size_t len,
partition = mpart->partition;
card = maple_get_drvdata(mdev);
/* simple sanity checks */
if (len < 1) {
error = -EIO;
goto failed;
}
numblocks = card->parts[partition].numblocks;
if (to + len > numblocks * card->blocklen)
len = numblocks * card->blocklen - to;
......@@ -544,9 +536,9 @@ static void vmu_queryblocks(struct mapleq *mq)
mtd_cur->flags = MTD_WRITEABLE|MTD_NO_ERASE;
mtd_cur->size = part_cur->numblocks * card->blocklen;
mtd_cur->erasesize = card->blocklen;
mtd_cur->write = vmu_flash_write;
mtd_cur->read = vmu_flash_read;
mtd_cur->sync = vmu_flash_sync;
mtd_cur->_write = vmu_flash_write;
mtd_cur->_read = vmu_flash_read;
mtd_cur->_sync = vmu_flash_sync;
mtd_cur->writesize = card->blocklen;
mpart = kmalloc(sizeof(struct mdev_part), GFP_KERNEL);
......
......@@ -142,7 +142,7 @@ static int __init init_sbc82xx_flash(void)
nr_parts = ARRAY_SIZE(smallflash_parts);
}
mtd_device_parse_register(sbcmtd[i], part_probes, 0,
mtd_device_parse_register(sbcmtd[i], part_probes, NULL,
defparts, nr_parts);
}
return 0;
......
......@@ -233,6 +233,7 @@ static int blktrans_open(struct block_device *bdev, fmode_t mode)
ret = __get_mtd_device(dev->mtd);
if (ret)
goto error_release;
dev->file_mode = mode;
unlock:
dev->open++;
......
......@@ -321,8 +321,12 @@ static int mtdblock_release(struct mtd_blktrans_dev *mbd)
mutex_unlock(&mtdblk->cache_mutex);
if (!--mtdblk->count) {
/* It was the last usage. Free the cache */
mtd_sync(mbd->mtd);
/*
* It was the last usage. Free the cache, but only sync if
* opened for writing.
*/
if (mbd->file_mode & FMODE_WRITE)
mtd_sync(mbd->mtd);
vfree(mtdblk->cache_data);
}
......
......@@ -405,7 +405,7 @@ static int mtdchar_writeoob(struct file *file, struct mtd_info *mtd,
if (length > 4096)
return -EINVAL;
if (!mtd->write_oob)
if (!mtd->_write_oob)
ret = -EOPNOTSUPP;
else
ret = access_ok(VERIFY_READ, ptr, length) ? 0 : -EFAULT;
......@@ -576,7 +576,7 @@ static int mtdchar_write_ioctl(struct mtd_info *mtd,
!access_ok(VERIFY_READ, req.usr_data, req.len) ||
!access_ok(VERIFY_READ, req.usr_oob, req.ooblen))
return -EFAULT;
if (!mtd->write_oob)
if (!mtd->_write_oob)
return -EOPNOTSUPP;
ops.mode = req.mode;
......
......@@ -72,8 +72,6 @@ concat_read(struct mtd_info *mtd, loff_t from, size_t len,
int ret = 0, err;
int i;
*retlen = 0;
for (i = 0; i < concat->num_subdev; i++) {
struct mtd_info *subdev = concat->subdev[i];
size_t size, retsize;
......@@ -126,11 +124,6 @@ concat_write(struct mtd_info *mtd, loff_t to, size_t len,
int err = -EINVAL;
int i;
if (!(mtd->flags & MTD_WRITEABLE))
return -EROFS;
*retlen = 0;
for (i = 0; i < concat->num_subdev; i++) {
struct mtd_info *subdev = concat->subdev[i];
size_t size, retsize;
......@@ -145,11 +138,7 @@ concat_write(struct mtd_info *mtd, loff_t to, size_t len,
else
size = len;
if (!(subdev->flags & MTD_WRITEABLE))
err = -EROFS;
else
err = mtd_write(subdev, to, size, &retsize, buf);
err = mtd_write(subdev, to, size, &retsize, buf);
if (err)
break;
......@@ -176,19 +165,10 @@ concat_writev(struct mtd_info *mtd, const struct kvec *vecs,
int i;
int err = -EINVAL;
if (!(mtd->flags & MTD_WRITEABLE))
return -EROFS;
*retlen = 0;
/* Calculate total length of data */
for (i = 0; i < count; i++)
total_len += vecs[i].iov_len;
/* Do not allow write past end of device */
if ((to + total_len) > mtd->size)
return -EINVAL;
/* Check alignment */
if (mtd->writesize > 1) {
uint64_t __to = to;
......@@ -224,12 +204,8 @@ concat_writev(struct mtd_info *mtd, const struct kvec *vecs,
old_iov_len = vecs_copy[entry_high].iov_len;
vecs_copy[entry_high].iov_len = size;
if (!(subdev->flags & MTD_WRITEABLE))
err = -EROFS;
else
err = mtd_writev(subdev, &vecs_copy[entry_low],
entry_high - entry_low + 1, to,
&retsize);
err = mtd_writev(subdev, &vecs_copy[entry_low],
entry_high - entry_low + 1, to, &retsize);
vecs_copy[entry_high].iov_len = old_iov_len - size;
vecs_copy[entry_high].iov_base += size;
......@@ -403,15 +379,6 @@ static int concat_erase(struct mtd_info *mtd, struct erase_info *instr)
uint64_t length, offset = 0;
struct erase_info *erase;
if (!(mtd->flags & MTD_WRITEABLE))
return -EROFS;
if (instr->addr > concat->mtd.size)
return -EINVAL;
if (instr->len + instr->addr > concat->mtd.size)
return -EINVAL;
/*
* Check for proper erase block alignment of the to-be-erased area.
* It is easier to do this based on the super device's erase
......@@ -459,8 +426,6 @@ static int concat_erase(struct mtd_info *mtd, struct erase_info *instr)
return -EINVAL;
}
instr->fail_addr = MTD_FAIL_ADDR_UNKNOWN;
/* make a local copy of instr to avoid modifying the caller's struct */
erase = kmalloc(sizeof (struct erase_info), GFP_KERNEL);
......@@ -499,10 +464,6 @@ static int concat_erase(struct mtd_info *mtd, struct erase_info *instr)
else
erase->len = length;
if (!(subdev->flags & MTD_WRITEABLE)) {
err = -EROFS;
break;
}
length -= erase->len;
if ((err = concat_dev_erase(subdev, erase))) {
/* sanity check: should never happen since
......@@ -538,9 +499,6 @@ static int concat_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
struct mtd_concat *concat = CONCAT(mtd);
int i, err = -EINVAL;
if ((len + ofs) > mtd->size)
return -EINVAL;
for (i = 0; i < concat->num_subdev; i++) {
struct mtd_info *subdev = concat->subdev[i];
uint64_t size;
......@@ -575,9 +533,6 @@ static int concat_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
struct mtd_concat *concat = CONCAT(mtd);
int i, err = 0;
if ((len + ofs) > mtd->size)
return -EINVAL;
for (i = 0; i < concat->num_subdev; i++) {
struct mtd_info *subdev = concat->subdev[i];
uint64_t size;
......@@ -650,9 +605,6 @@ static int concat_block_isbad(struct mtd_info *mtd, loff_t ofs)
if (!mtd_can_have_bb(concat->subdev[0]))
return res;
if (ofs > mtd->size)
return -EINVAL;
for (i = 0; i < concat->num_subdev; i++) {
struct mtd_info *subdev = concat->subdev[i];
......@@ -673,12 +625,6 @@ static int concat_block_markbad(struct mtd_info *mtd, loff_t ofs)
struct mtd_concat *concat = CONCAT(mtd);
int i, err = -EINVAL;
if (!mtd_can_have_bb(concat->subdev[0]))
return 0;
if (ofs > mtd->size)
return -EINVAL;
for (i = 0; i < concat->num_subdev; i++) {
struct mtd_info *subdev = concat->subdev[i];
......@@ -716,10 +662,6 @@ static unsigned long concat_get_unmapped_area(struct mtd_info *mtd,
continue;
}
/* we've found the subdev over which the mapping will reside */
if (offset + len > subdev->size)
return (unsigned long) -EINVAL;
return mtd_get_unmapped_area(subdev, len, offset, flags);
}
......@@ -777,16 +719,16 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c
concat->mtd.subpage_sft = subdev[0]->subpage_sft;
concat->mtd.oobsize = subdev[0]->oobsize;
concat->mtd.oobavail = subdev[0]->oobavail;
if (subdev[0]->writev)
concat->mtd.writev = concat_writev;
if (subdev[0]->read_oob)
concat->mtd.read_oob = concat_read_oob;
if (subdev[0]->write_oob)
concat->mtd.write_oob = concat_write_oob;
if (subdev[0]->block_isbad)
concat->mtd.block_isbad = concat_block_isbad;
if (subdev[0]->block_markbad)
concat->mtd.block_markbad = concat_block_markbad;
if (subdev[0]->_writev)
concat->mtd._writev = concat_writev;
if (subdev[0]->_read_oob)
concat->mtd._read_oob = concat_read_oob;
if (subdev[0]->_write_oob)
concat->mtd._write_oob = concat_write_oob;
if (subdev[0]->_block_isbad)
concat->mtd._block_isbad = concat_block_isbad;
if (subdev[0]->_block_markbad)
concat->mtd._block_markbad = concat_block_markbad;
concat->mtd.ecc_stats.badblocks = subdev[0]->ecc_stats.badblocks;
......@@ -833,8 +775,8 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c
if (concat->mtd.writesize != subdev[i]->writesize ||
concat->mtd.subpage_sft != subdev[i]->subpage_sft ||
concat->mtd.oobsize != subdev[i]->oobsize ||
!concat->mtd.read_oob != !subdev[i]->read_oob ||
!concat->mtd.write_oob != !subdev[i]->write_oob) {
!concat->mtd._read_oob != !subdev[i]->_read_oob ||
!concat->mtd._write_oob != !subdev[i]->_write_oob) {
kfree(concat);
printk("Incompatible OOB or ECC data on \"%s\"\n",
subdev[i]->name);
......@@ -849,15 +791,15 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c
concat->num_subdev = num_devs;
concat->mtd.name = name;
concat->mtd.erase = concat_erase;
concat->mtd.read = concat_read;
concat->mtd.write = concat_write;
concat->mtd.sync = concat_sync;
concat->mtd.lock = concat_lock;
concat->mtd.unlock = concat_unlock;
concat->mtd.suspend = concat_suspend;
concat->mtd.resume = concat_resume;
concat->mtd.get_unmapped_area = concat_get_unmapped_area;
concat->mtd._erase = concat_erase;
concat->mtd._read = concat_read;
concat->mtd._write = concat_write;
concat->mtd._sync = concat_sync;
concat->mtd._lock = concat_lock;
concat->mtd._unlock = concat_unlock;
concat->mtd._suspend = concat_suspend;
concat->mtd._resume = concat_resume;
concat->mtd._get_unmapped_area = concat_get_unmapped_area;
/*
* Combine the erase block size info of the subdevices:
......
......@@ -107,7 +107,7 @@ static LIST_HEAD(mtd_notifiers);
*/
static void mtd_release(struct device *dev)
{
struct mtd_info *mtd = dev_get_drvdata(dev);
struct mtd_info __maybe_unused *mtd = dev_get_drvdata(dev);
dev_t index = MTD_DEVT(mtd->index);
/* remove /dev/mtdXro node if needed */
......@@ -126,7 +126,7 @@ static int mtd_cls_resume(struct device *dev)
{
struct mtd_info *mtd = dev_get_drvdata(dev);
if (mtd && mtd->resume)
if (mtd)
mtd_resume(mtd);
return 0;
}
......@@ -610,8 +610,8 @@ int __get_mtd_device(struct mtd_info *mtd)
if (!try_module_get(mtd->owner))
return -ENODEV;
if (mtd->get_device) {
err = mtd->get_device(mtd);
if (mtd->_get_device) {
err = mtd->_get_device(mtd);
if (err) {
module_put(mtd->owner);
......@@ -675,13 +675,266 @@ void __put_mtd_device(struct mtd_info *mtd)
--mtd->usecount;
BUG_ON(mtd->usecount < 0);
if (mtd->put_device)
mtd->put_device(mtd);
if (mtd->_put_device)
mtd->_put_device(mtd);
module_put(mtd->owner);
}
EXPORT_SYMBOL_GPL(__put_mtd_device);
/*
* Erase is an asynchronous operation. Device drivers are supposed
* to call instr->callback() whenever the operation completes, even
* if it completes with a failure.
* Callers are supposed to pass a callback function and wait for it
* to be called before writing to the block.
*/
int mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
{
if (instr->addr > mtd->size || instr->len > mtd->size - instr->addr)
return -EINVAL;
if (!(mtd->flags & MTD_WRITEABLE))
return -EROFS;
instr->fail_addr = MTD_FAIL_ADDR_UNKNOWN;
if (!instr->len) {
instr->state = MTD_ERASE_DONE;
mtd_erase_callback(instr);
return 0;
}
return mtd->_erase(mtd, instr);
}
EXPORT_SYMBOL_GPL(mtd_erase);
/*
* This stuff for eXecute-In-Place. phys is optional and may be set to NULL.
*/
int mtd_point(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen,
void **virt, resource_size_t *phys)
{
*retlen = 0;
*virt = NULL;
if (phys)
*phys = 0;
if (!mtd->_point)
return -EOPNOTSUPP;
if (from < 0 || from > mtd->size || len > mtd->size - from)
return -EINVAL;
if (!len)
return 0;
return mtd->_point(mtd, from, len, retlen, virt, phys);
}
EXPORT_SYMBOL_GPL(mtd_point);
/* We probably shouldn't allow XIP if the unpoint isn't a NULL */
int mtd_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
{
if (!mtd->_point)
return -EOPNOTSUPP;
if (from < 0 || from > mtd->size || len > mtd->size - from)
return -EINVAL;
if (!len)
return 0;
return mtd->_unpoint(mtd, from, len);
}
EXPORT_SYMBOL_GPL(mtd_unpoint);
/*
* Allow NOMMU mmap() to directly map the device (if not NULL)
* - return the address to which the offset maps
* - return -ENOSYS to indicate refusal to do the mapping
*/
unsigned long mtd_get_unmapped_area(struct mtd_info *mtd, unsigned long len,
unsigned long offset, unsigned long flags)
{
if (!mtd->_get_unmapped_area)
return -EOPNOTSUPP;
if (offset > mtd->size || len > mtd->size - offset)
return -EINVAL;
return mtd->_get_unmapped_area(mtd, len, offset, flags);
}
EXPORT_SYMBOL_GPL(mtd_get_unmapped_area);
int mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen,
u_char *buf)
{
*retlen = 0;
if (from < 0 || from > mtd->size || len > mtd->size - from)
return -EINVAL;
if (!len)
return 0;
return mtd->_read(mtd, from, len, retlen, buf);
}
EXPORT_SYMBOL_GPL(mtd_read);
int mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
const u_char *buf)
{
*retlen = 0;
if (to < 0 || to > mtd->size || len > mtd->size - to)
return -EINVAL;
if (!mtd->_write || !(mtd->flags & MTD_WRITEABLE))
return -EROFS;
if (!len)
return 0;
return mtd->_write(mtd, to, len, retlen, buf);
}
EXPORT_SYMBOL_GPL(mtd_write);
/*
* In blackbox flight recorder like scenarios we want to make successful writes
* in interrupt context. panic_write() is only intended to be called when its
* known the kernel is about to panic and we need the write to succeed. Since
* the kernel is not going to be running for much longer, this function can
* break locks and delay to ensure the write succeeds (but not sleep).
*/
int mtd_panic_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
const u_char *buf)
{
*retlen = 0;
if (!mtd->_panic_write)
return -EOPNOTSUPP;
if (to < 0 || to > mtd->size || len > mtd->size - to)
return -EINVAL;
if (!(mtd->flags & MTD_WRITEABLE))
return -EROFS;
if (!len)
return 0;
return mtd->_panic_write(mtd, to, len, retlen, buf);
}
EXPORT_SYMBOL_GPL(mtd_panic_write);
/*
* Method to access the protection register area, present in some flash
* devices. The user data is one time programmable but the factory data is read
* only.
*/
int mtd_get_fact_prot_info(struct mtd_info *mtd, struct otp_info *buf,
size_t len)
{
if (!mtd->_get_fact_prot_info)
return -EOPNOTSUPP;
if (!len)
return 0;
return mtd->_get_fact_prot_info(mtd, buf, len);
}
EXPORT_SYMBOL_GPL(mtd_get_fact_prot_info);
int mtd_read_fact_prot_reg(struct mtd_info *mtd, loff_t from, size_t len,
size_t *retlen, u_char *buf)
{
*retlen = 0;
if (!mtd->_read_fact_prot_reg)
return -EOPNOTSUPP;
if (!len)
return 0;
return mtd->_read_fact_prot_reg(mtd, from, len, retlen, buf);
}
EXPORT_SYMBOL_GPL(mtd_read_fact_prot_reg);
int mtd_get_user_prot_info(struct mtd_info *mtd, struct otp_info *buf,
size_t len)
{
if (!mtd->_get_user_prot_info)
return -EOPNOTSUPP;
if (!len)
return 0;
return mtd->_get_user_prot_info(mtd, buf, len);
}
EXPORT_SYMBOL_GPL(mtd_get_user_prot_info);
int mtd_read_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len,
size_t *retlen, u_char *buf)
{
*retlen = 0;
if (!mtd->_read_user_prot_reg)
return -EOPNOTSUPP;
if (!len)
return 0;
return mtd->_read_user_prot_reg(mtd, from, len, retlen, buf);
}
EXPORT_SYMBOL_GPL(mtd_read_user_prot_reg);
int mtd_write_user_prot_reg(struct mtd_info *mtd, loff_t to, size_t len,
size_t *retlen, u_char *buf)
{
*retlen = 0;
if (!mtd->_write_user_prot_reg)
return -EOPNOTSUPP;
if (!len)
return 0;
return mtd->_write_user_prot_reg(mtd, to, len, retlen, buf);
}
EXPORT_SYMBOL_GPL(mtd_write_user_prot_reg);
int mtd_lock_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len)
{
if (!mtd->_lock_user_prot_reg)
return -EOPNOTSUPP;
if (!len)
return 0;
return mtd->_lock_user_prot_reg(mtd, from, len);
}
EXPORT_SYMBOL_GPL(mtd_lock_user_prot_reg);
/* Chip-supported device locking */
int mtd_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
{
if (!mtd->_lock)
return -EOPNOTSUPP;
if (ofs < 0 || ofs > mtd->size || len > mtd->size - ofs)
return -EINVAL;
if (!len)
return 0;
return mtd->_lock(mtd, ofs, len);
}
EXPORT_SYMBOL_GPL(mtd_lock);
int mtd_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
{
if (!mtd->_unlock)
return -EOPNOTSUPP;
if (ofs < 0 || ofs > mtd->size || len > mtd->size - ofs)
return -EINVAL;
if (!len)
return 0;
return mtd->_unlock(mtd, ofs, len);
}
EXPORT_SYMBOL_GPL(mtd_unlock);
int mtd_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len)
{
if (!mtd->_is_locked)
return -EOPNOTSUPP;
if (ofs < 0 || ofs > mtd->size || len > mtd->size - ofs)
return -EINVAL;
if (!len)
return 0;
return mtd->_is_locked(mtd, ofs, len);
}
EXPORT_SYMBOL_GPL(mtd_is_locked);
int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs)
{
if (!mtd->_block_isbad)
return 0;
if (ofs < 0 || ofs > mtd->size)
return -EINVAL;
return mtd->_block_isbad(mtd, ofs);
}
EXPORT_SYMBOL_GPL(mtd_block_isbad);
int mtd_block_markbad(struct mtd_info *mtd, loff_t ofs)
{
if (!mtd->_block_markbad)
return -EOPNOTSUPP;
if (ofs < 0 || ofs > mtd->size)
return -EINVAL;
if (!(mtd->flags & MTD_WRITEABLE))
return -EROFS;
return mtd->_block_markbad(mtd, ofs);
}
EXPORT_SYMBOL_GPL(mtd_block_markbad);
/*
* default_mtd_writev - the default writev method
* @mtd: mtd device description object pointer
......@@ -729,9 +982,11 @@ int mtd_writev(struct mtd_info *mtd, const struct kvec *vecs,
unsigned long count, loff_t to, size_t *retlen)
{
*retlen = 0;
if (!mtd->writev)
if (!(mtd->flags & MTD_WRITEABLE))
return -EROFS;
if (!mtd->_writev)
return default_mtd_writev(mtd, vecs, count, to, retlen);
return mtd->writev(mtd, vecs, count, to, retlen);
return mtd->_writev(mtd, vecs, count, to, retlen);
}
EXPORT_SYMBOL_GPL(mtd_writev);
......
......@@ -169,7 +169,7 @@ static void mtdoops_workfunc_erase(struct work_struct *work)
cxt->nextpage = 0;
}
while (mtd_can_have_bb(mtd)) {
while (1) {
ret = mtd_block_isbad(mtd, cxt->nextpage * record_size);
if (!ret)
break;
......@@ -199,9 +199,9 @@ static void mtdoops_workfunc_erase(struct work_struct *work)
return;
}
if (mtd_can_have_bb(mtd) && ret == -EIO) {
if (ret == -EIO) {
ret = mtd_block_markbad(mtd, cxt->nextpage * record_size);
if (ret < 0) {
if (ret < 0 && ret != -EOPNOTSUPP) {
printk(KERN_ERR "mtdoops: block_markbad failed, aborting\n");
return;
}
......@@ -257,8 +257,7 @@ static void find_next_position(struct mtdoops_context *cxt)
size_t retlen;
for (page = 0; page < cxt->oops_pages; page++) {
if (mtd_can_have_bb(mtd) &&
mtd_block_isbad(mtd, page * record_size))
if (mtd_block_isbad(mtd, page * record_size))
continue;
/* Assume the page is used */
mark_page_used(cxt, page);
......
This diff is collapsed.
......@@ -314,6 +314,26 @@ config MTD_NAND_DISKONCHIP_BBTWRITE
load time (assuming you build diskonchip as a module) with the module
parameter "inftl_bbt_write=1".
config MTD_NAND_DOCG4
tristate "Support for DiskOnChip G4 (EXPERIMENTAL)"
depends on EXPERIMENTAL
select BCH
select BITREVERSE
help
Support for diskonchip G4 nand flash, found in various smartphones and
PDAs, among them the Palm Treo680, HTC Prophet and Wizard, Toshiba
Portege G900, Asus P526, and O2 XDA Zinc.
With this driver you will be able to use UBI and create a ubifs on the
device, so you may wish to consider enabling UBI and UBIFS as well.
These devices ship with the Mys/Sandisk SAFTL formatting, for which
there is currently no mtd parser, so you may want to use command line
partitioning to segregate write-protected blocks. On the Treo680, the
first five erase blocks (256KiB each) are write-protected, followed
by the block containing the saftl partition table. This is probably
typical.
config MTD_NAND_SHARPSL
tristate "Support for NAND Flash on Sharp SL Series (C7xx + others)"
depends on ARCH_PXA
......@@ -421,7 +441,6 @@ config MTD_NAND_NANDSIM
config MTD_NAND_GPMI_NAND
bool "GPMI NAND Flash Controller driver"
depends on MTD_NAND && (SOC_IMX23 || SOC_IMX28)
select MTD_CMDLINE_PARTS
help
Enables NAND Flash support for IMX23 or IMX28.
The GPMI controller is very powerful, with the help of BCH
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment