diff options
Diffstat (limited to 'drivers/mtd')
112 files changed, 2636 insertions, 2590 deletions
diff --git a/drivers/mtd/ar7part.c b/drivers/mtd/ar7part.c index 945393129952..7c057a05adb6 100644 --- a/drivers/mtd/ar7part.c +++ b/drivers/mtd/ar7part.c @@ -26,19 +26,16 @@ #include <linux/mtd/mtd.h> #include <linux/mtd/partitions.h> #include <linux/bootmem.h> -#include <linux/magic.h> #include <linux/module.h> +#include <uapi/linux/magic.h> + #define AR7_PARTS 4 #define ROOT_OFFSET 0xe0000 #define LOADER_MAGIC1 le32_to_cpu(0xfeedfa42) #define LOADER_MAGIC2 le32_to_cpu(0xfeed1281) -#ifndef SQUASHFS_MAGIC -#define SQUASHFS_MAGIC 0x73717368 -#endif - struct ar7_bin_rec { unsigned int checksum; unsigned int length; diff --git a/drivers/mtd/bcm63xxpart.c b/drivers/mtd/bcm63xxpart.c index 63d2a64331f7..6eeb84c81bc2 100644 --- a/drivers/mtd/bcm63xxpart.c +++ b/drivers/mtd/bcm63xxpart.c @@ -37,8 +37,7 @@ #define BCM63XX_EXTENDED_SIZE 0xBFC00000 /* Extended flash address */ -#define BCM63XX_MIN_CFE_SIZE 0x10000 /* always at least 64KiB */ -#define BCM63XX_MIN_NVRAM_SIZE 0x10000 /* always at least 64KiB */ +#define BCM63XX_CFE_BLOCK_SIZE 0x10000 /* always at least 64KiB */ #define BCM63XX_CFE_MAGIC_OFFSET 0x4e0 @@ -79,7 +78,7 @@ static int bcm63xx_parse_cfe_partitions(struct mtd_info *master, unsigned int rootfsaddr, kerneladdr, spareaddr; unsigned int rootfslen, kernellen, sparelen, totallen; unsigned int cfelen, nvramlen; - int namelen = 0; + unsigned int cfe_erasesize; int i; u32 computed_crc; bool rootfs_first = false; @@ -87,8 +86,11 @@ static int bcm63xx_parse_cfe_partitions(struct mtd_info *master, if (bcm63xx_detect_cfe(master)) return -EINVAL; - cfelen = max_t(uint32_t, master->erasesize, BCM63XX_MIN_CFE_SIZE); - nvramlen = max_t(uint32_t, master->erasesize, BCM63XX_MIN_NVRAM_SIZE); + cfe_erasesize = max_t(uint32_t, master->erasesize, + BCM63XX_CFE_BLOCK_SIZE); + + cfelen = cfe_erasesize; + nvramlen = cfe_erasesize; /* Allocate memory for buffer */ buf = vmalloc(sizeof(struct bcm_tag)); @@ -121,7 +123,6 @@ static int bcm63xx_parse_cfe_partitions(struct mtd_info *master, kerneladdr = kerneladdr - BCM63XX_EXTENDED_SIZE; rootfsaddr = rootfsaddr - BCM63XX_EXTENDED_SIZE; spareaddr = roundup(totallen, master->erasesize) + cfelen; - sparelen = master->size - spareaddr - nvramlen; if (rootfsaddr < kerneladdr) { /* default Broadcom layout */ @@ -139,19 +140,15 @@ static int bcm63xx_parse_cfe_partitions(struct mtd_info *master, rootfslen = 0; rootfsaddr = 0; spareaddr = cfelen; - sparelen = master->size - cfelen - nvramlen; } + sparelen = master->size - spareaddr - nvramlen; /* Determine number of partitions */ - namelen = 8; - if (rootfslen > 0) { + if (rootfslen > 0) nrparts++; - namelen += 6; - } - if (kernellen > 0) { + + if (kernellen > 0) nrparts++; - namelen += 6; - } /* Ask kernel for more memory */ parts = kzalloc(sizeof(*parts) * nrparts + 10 * nrparts, GFP_KERNEL); @@ -193,17 +190,16 @@ static int bcm63xx_parse_cfe_partitions(struct mtd_info *master, parts[curpart].name = "nvram"; parts[curpart].offset = master->size - nvramlen; parts[curpart].size = nvramlen; + curpart++; /* Global partition "linux" to make easy firmware upgrade */ - curpart++; parts[curpart].name = "linux"; parts[curpart].offset = cfelen; parts[curpart].size = master->size - cfelen - nvramlen; for (i = 0; i < nrparts; i++) - pr_info("Partition %d is %s offset %lx and length %lx\n", i, - parts[i].name, (long unsigned int)(parts[i].offset), - (long unsigned int)(parts[i].size)); + pr_info("Partition %d is %s offset %llx and length %llx\n", i, + parts[i].name, parts[i].offset, parts[i].size); pr_info("Spare partition is offset %x and length %x\n", spareaddr, sparelen); diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index 5ff5c4a16943..b86197286f24 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c @@ -1536,8 +1536,20 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, UDELAY(map, chip, adr, 1); } - /* reset on all failures. */ - map_write( map, CMD(0xF0), chip->start ); + /* + * Recovery from write-buffer programming failures requires + * the write-to-buffer-reset sequence. Since the last part + * of the sequence also works as a normal reset, we can run + * the same commands regardless of why we are here. + * See e.g. + * http://www.spansion.com/Support/Application%20Notes/MirrorBit_Write_Buffer_Prog_Page_Buffer_Read_AN.pdf + */ + cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, + cfi->device_type, NULL); + cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, + cfi->device_type, NULL); + cfi_send_gen_cmd(0xF0, cfi->addr_unlock1, chip->start, map, cfi, + cfi->device_type, NULL); xip_enable(map, chip, adr); /* FIXME - should have reset delay before continuing */ diff --git a/drivers/mtd/cmdlinepart.c b/drivers/mtd/cmdlinepart.c index aed1b8a63c9f..c533f27d863f 100644 --- a/drivers/mtd/cmdlinepart.c +++ b/drivers/mtd/cmdlinepart.c @@ -56,8 +56,8 @@ /* special size referring to all the remaining space in a partition */ -#define SIZE_REMAINING UINT_MAX -#define OFFSET_CONTINUOUS UINT_MAX +#define SIZE_REMAINING ULLONG_MAX +#define OFFSET_CONTINUOUS ULLONG_MAX struct cmdline_mtd_partition { struct cmdline_mtd_partition *next; @@ -89,7 +89,7 @@ static struct mtd_partition * newpart(char *s, int extra_mem_size) { struct mtd_partition *parts; - unsigned long size, offset = OFFSET_CONTINUOUS; + unsigned long long size, offset = OFFSET_CONTINUOUS; char *name; int name_len; unsigned char *extra_mem; @@ -104,7 +104,8 @@ static struct mtd_partition * newpart(char *s, } else { size = memparse(s, &s); if (size < PAGE_SIZE) { - printk(KERN_ERR ERRP "partition size too small (%lx)\n", size); + printk(KERN_ERR ERRP "partition size too small (%llx)\n", + size); return ERR_PTR(-EINVAL); } } @@ -296,7 +297,7 @@ static int parse_cmdline_partitions(struct mtd_info *master, struct mtd_partition **pparts, struct mtd_part_parser_data *data) { - unsigned long offset; + unsigned long long offset; int i, err; struct cmdline_mtd_partition *part; const char *mtd_id = master->name; @@ -308,48 +309,52 @@ static int parse_cmdline_partitions(struct mtd_info *master, return err; } + /* + * Search for the partition definition matching master->name. + * If master->name is not set, stop at first partition definition. + */ for (part = partitions; part; part = part->next) { - if ((!mtd_id) || (!strcmp(part->mtd_id, mtd_id))) { - for (i = 0, offset = 0; i < part->num_parts; i++) { - if (part->parts[i].offset == OFFSET_CONTINUOUS) - part->parts[i].offset = offset; - else - offset = part->parts[i].offset; - - if (part->parts[i].size == SIZE_REMAINING) - part->parts[i].size = master->size - offset; - - if (part->parts[i].size == 0) { - printk(KERN_WARNING ERRP - "%s: skipping zero sized partition\n", - part->mtd_id); - part->num_parts--; - memmove(&part->parts[i], - &part->parts[i + 1], - sizeof(*part->parts) * (part->num_parts - i)); - continue; - } - - if (offset + part->parts[i].size > master->size) { - printk(KERN_WARNING ERRP - "%s: partitioning exceeds flash size, truncating\n", - part->mtd_id); - part->parts[i].size = master->size - offset; - } - offset += part->parts[i].size; - } - - *pparts = kmemdup(part->parts, - sizeof(*part->parts) * part->num_parts, - GFP_KERNEL); - if (!*pparts) - return -ENOMEM; - - return part->num_parts; + if ((!mtd_id) || (!strcmp(part->mtd_id, mtd_id))) + break; + } + + if (!part) + return 0; + + for (i = 0, offset = 0; i < part->num_parts; i++) { + if (part->parts[i].offset == OFFSET_CONTINUOUS) + part->parts[i].offset = offset; + else + offset = part->parts[i].offset; + + if (part->parts[i].size == SIZE_REMAINING) + part->parts[i].size = master->size - offset; + + if (part->parts[i].size == 0) { + printk(KERN_WARNING ERRP + "%s: skipping zero sized partition\n", + part->mtd_id); + part->num_parts--; + memmove(&part->parts[i], &part->parts[i + 1], + sizeof(*part->parts) * (part->num_parts - i)); + continue; } + + if (offset + part->parts[i].size > master->size) { + printk(KERN_WARNING ERRP + "%s: partitioning exceeds flash size, truncating\n", + part->mtd_id); + part->parts[i].size = master->size - offset; + } + offset += part->parts[i].size; } - return 0; + *pparts = kmemdup(part->parts, sizeof(*part->parts) * part->num_parts, + GFP_KERNEL); + if (!*pparts) + return -ENOMEM; + + return part->num_parts; } diff --git a/drivers/mtd/devices/bcm47xxsflash.c b/drivers/mtd/devices/bcm47xxsflash.c index 2dc5a6f3fd57..4714584aa993 100644 --- a/drivers/mtd/devices/bcm47xxsflash.c +++ b/drivers/mtd/devices/bcm47xxsflash.c @@ -66,7 +66,7 @@ out: return err; } -static int __devexit bcm47xxsflash_remove(struct platform_device *pdev) +static int bcm47xxsflash_remove(struct platform_device *pdev) { struct bcma_sflash *sflash = dev_get_platdata(&pdev->dev); @@ -77,7 +77,7 @@ static int __devexit bcm47xxsflash_remove(struct platform_device *pdev) } static struct platform_driver bcma_sflash_driver = { - .remove = __devexit_p(bcm47xxsflash_remove), + .remove = bcm47xxsflash_remove, .driver = { .name = "bcma_sflash", .owner = THIS_MODULE, diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c index 681e2ee0f2d6..e081bfeaaf7d 100644 --- a/drivers/mtd/devices/block2mtd.c +++ b/drivers/mtd/devices/block2mtd.c @@ -62,6 +62,7 @@ static int _block2mtd_erase(struct block2mtd_dev *dev, loff_t to, size_t len) memset(page_address(page), 0xff, PAGE_SIZE); set_page_dirty(page); unlock_page(page); + balance_dirty_pages_ratelimited(mapping); break; } @@ -152,6 +153,7 @@ static int _block2mtd_write(struct block2mtd_dev *dev, const u_char *buf, memcpy(page_address(page) + offset, buf, cpylen); set_page_dirty(page); unlock_page(page); + balance_dirty_pages_ratelimited(mapping); } page_cache_release(page); @@ -433,7 +435,7 @@ static int __init block2mtd_init(void) } -static void __devexit block2mtd_exit(void) +static void block2mtd_exit(void) { struct list_head *pos, *next; diff --git a/drivers/mtd/devices/docg3.c b/drivers/mtd/devices/docg3.c index d34d83b8f9c2..8510ccb9c6f0 100644 --- a/drivers/mtd/devices/docg3.c +++ b/drivers/mtd/devices/docg3.c @@ -1440,7 +1440,7 @@ static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, oobdelta = mtd->ecclayout->oobavail; break; default: - oobdelta = 0; + return -EINVAL; } if ((len % DOC_LAYOUT_PAGE_SIZE) || (ooblen % oobdelta) || (ofs % DOC_LAYOUT_PAGE_SIZE)) diff --git a/drivers/mtd/devices/docprobe.c b/drivers/mtd/devices/docprobe.c index 706b847b46b3..88b3fd3e18a7 100644 --- a/drivers/mtd/devices/docprobe.c +++ b/drivers/mtd/devices/docprobe.c @@ -70,8 +70,6 @@ static unsigned long __initdata doc_locations[] = { 0xe0000, 0xe2000, 0xe4000, 0xe6000, 0xe8000, 0xea000, 0xec000, 0xee000, #endif /* CONFIG_MTD_DOCPROBE_HIGH */ -#else -#warning Unknown architecture for DiskOnChip. No default probe locations defined #endif 0xffffffff }; diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index 03838bab1f59..4eeeb2d7f6ea 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c @@ -73,14 +73,6 @@ #define MAX_READY_WAIT_JIFFIES (40 * HZ) /* M25P16 specs 40s max chip erase */ #define MAX_CMD_SIZE 5 -#ifdef CONFIG_M25PXX_USE_FAST_READ -#define OPCODE_READ OPCODE_FAST_READ -#define FAST_READ_DUMMY_BYTE 1 -#else -#define OPCODE_READ OPCODE_NORM_READ -#define FAST_READ_DUMMY_BYTE 0 -#endif - #define JEDEC_MFR(_jedec_id) ((_jedec_id) >> 16) /****************************************************************************/ @@ -93,6 +85,7 @@ struct m25p { u16 addr_width; u8 erase_opcode; u8 *command; + bool fast_read; }; static inline struct m25p *mtd_to_m25p(struct mtd_info *mtd) @@ -168,6 +161,7 @@ static inline int set_4byte(struct m25p *flash, u32 jedec_id, int enable) { switch (JEDEC_MFR(jedec_id)) { case CFI_MFR_MACRONIX: + case 0xEF /* winbond */: flash->command[0] = enable ? OPCODE_EN4B : OPCODE_EX4B; return spi_write(flash->spi, flash->command, 1); default: @@ -342,6 +336,7 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len, struct m25p *flash = mtd_to_m25p(mtd); struct spi_transfer t[2]; struct spi_message m; + uint8_t opcode; pr_debug("%s: %s from 0x%08x, len %zd\n", dev_name(&flash->spi->dev), __func__, (u32)from, len); @@ -354,7 +349,7 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len, * Should add 1 byte DUMMY_BYTE. */ t[0].tx_buf = flash->command; - t[0].len = m25p_cmdsz(flash) + FAST_READ_DUMMY_BYTE; + t[0].len = m25p_cmdsz(flash) + (flash->fast_read ? 1 : 0); spi_message_add_tail(&t[0], &m); t[1].rx_buf = buf; @@ -376,12 +371,14 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len, */ /* Set up the write data buffer. */ - flash->command[0] = OPCODE_READ; + opcode = flash->fast_read ? OPCODE_FAST_READ : OPCODE_NORM_READ; + flash->command[0] = opcode; m25p_addr2cmd(flash, from, flash->command); spi_sync(flash->spi, &m); - *retlen = m.actual_length - m25p_cmdsz(flash) - FAST_READ_DUMMY_BYTE; + *retlen = m.actual_length - m25p_cmdsz(flash) - + (flash->fast_read ? 1 : 0); mutex_unlock(&flash->lock); @@ -664,7 +661,8 @@ static const struct spi_device_id m25p_ids[] = { { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) }, /* Micron */ - { "n25q128", INFO(0x20ba18, 0, 64 * 1024, 256, 0) }, + { "n25q128a11", INFO(0x20bb18, 0, 64 * 1024, 256, 0) }, + { "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, 0) }, { "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K) }, /* Spansion -- single (large) sector size only, at least @@ -745,6 +743,8 @@ static const struct spi_device_id m25p_ids[] = { { "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) }, { "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) }, { "w25q80", INFO(0xef5014, 0, 64 * 1024, 16, SECT_4K) }, + { "w25q80bl", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K) }, + { "w25q256", INFO(0xef4019, 0, 64 * 1024, 512, SECT_4K) }, /* Catalyst / On Semiconductor -- non-JEDEC */ { "cat25c11", CAT25_INFO( 16, 8, 16, 1) }, @@ -756,7 +756,7 @@ static const struct spi_device_id m25p_ids[] = { }; MODULE_DEVICE_TABLE(spi, m25p_ids); -static const struct spi_device_id *__devinit jedec_probe(struct spi_device *spi) +static const struct spi_device_id *jedec_probe(struct spi_device *spi) { int tmp; u8 code = OPCODE_RDID; @@ -801,7 +801,7 @@ static const struct spi_device_id *__devinit jedec_probe(struct spi_device *spi) * matches what the READ command supports, at least until this driver * understands FAST_READ (for clocks over 25 MHz). */ -static int __devinit m25p_probe(struct spi_device *spi) +static int m25p_probe(struct spi_device *spi) { const struct spi_device_id *id = spi_get_device_id(spi); struct flash_platform_data *data; @@ -809,9 +809,10 @@ static int __devinit m25p_probe(struct spi_device *spi) struct flash_info *info; unsigned i; struct mtd_part_parser_data ppdata; + struct device_node __maybe_unused *np = spi->dev.of_node; #ifdef CONFIG_MTD_OF_PARTS - if (!of_device_is_available(spi->dev.of_node)) + if (!of_device_is_available(np)) return -ENODEV; #endif @@ -863,7 +864,8 @@ static int __devinit m25p_probe(struct spi_device *spi) flash = kzalloc(sizeof *flash, GFP_KERNEL); if (!flash) return -ENOMEM; - flash->command = kmalloc(MAX_CMD_SIZE + FAST_READ_DUMMY_BYTE, GFP_KERNEL); + flash->command = kmalloc(MAX_CMD_SIZE + (flash->fast_read ? 1 : 0), + GFP_KERNEL); if (!flash->command) { kfree(flash); return -ENOMEM; @@ -920,6 +922,16 @@ static int __devinit m25p_probe(struct spi_device *spi) flash->page_size = info->page_size; flash->mtd.writebufsize = flash->page_size; + flash->fast_read = false; +#ifdef CONFIG_OF + if (np && of_property_read_bool(np, "m25p,fast-read")) + flash->fast_read = true; +#endif + +#ifdef CONFIG_M25PXX_USE_FAST_READ + flash->fast_read = true; +#endif + if (info->addr_width) flash->addr_width = info->addr_width; else { @@ -961,7 +973,7 @@ static int __devinit m25p_probe(struct spi_device *spi) } -static int __devexit m25p_remove(struct spi_device *spi) +static int m25p_remove(struct spi_device *spi) { struct m25p *flash = dev_get_drvdata(&spi->dev); int status; @@ -983,7 +995,7 @@ static struct spi_driver m25p80_driver = { }, .id_table = m25p_ids, .probe = m25p_probe, - .remove = __devexit_p(m25p_remove), + .remove = m25p_remove, /* REVISIT: many of these chips have deep power-down modes, which * should clearly be entered on suspend() to minimize power use. diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c index 928fb0e6d73a..ea7ea7b595d8 100644 --- a/drivers/mtd/devices/mtd_dataflash.c +++ b/drivers/mtd/devices/mtd_dataflash.c @@ -618,7 +618,7 @@ static char *otp_setup(struct mtd_info *device, char revision) /* * Register DataFlash device with MTD subsystem. */ -static int __devinit +static int add_dataflash_otp(struct spi_device *spi, char *name, int nr_pages, int pagesize, int pageoffset, char revision) { @@ -679,7 +679,7 @@ add_dataflash_otp(struct spi_device *spi, char *name, return err; } -static inline int __devinit +static inline int add_dataflash(struct spi_device *spi, char *name, int nr_pages, int pagesize, int pageoffset) { @@ -705,7 +705,7 @@ struct flash_info { #define IS_POW2PS 0x0001 /* uses 2^N byte pages */ }; -static struct flash_info __devinitdata dataflash_data [] = { +static struct flash_info dataflash_data[] = { /* * NOTE: chips with SUP_POW2PS (rev D and up) need two entries, @@ -740,7 +740,7 @@ static struct flash_info __devinitdata dataflash_data [] = { { "at45db642d", 0x1f2800, 8192, 1024, 10, SUP_POW2PS | IS_POW2PS}, }; -static struct flash_info *__devinit jedec_probe(struct spi_device *spi) +static struct flash_info *jedec_probe(struct spi_device *spi) { int tmp; uint8_t code = OP_READ_ID; @@ -823,7 +823,7 @@ static struct flash_info *__devinit jedec_probe(struct spi_device *spi) * AT45DB0642 64Mbit (8M) xx111xxx (0x3c) 8192 1056 11 * AT45DB1282 128Mbit (16M) xx0100xx (0x10) 16384 1056 11 */ -static int __devinit dataflash_probe(struct spi_device *spi) +static int dataflash_probe(struct spi_device *spi) { int status; struct flash_info *info; @@ -897,7 +897,7 @@ static int __devinit dataflash_probe(struct spi_device *spi) return status; } -static int __devexit dataflash_remove(struct spi_device *spi) +static int dataflash_remove(struct spi_device *spi) { struct dataflash *flash = dev_get_drvdata(&spi->dev); int status; @@ -920,7 +920,7 @@ static struct spi_driver dataflash_driver = { }, .probe = dataflash_probe, - .remove = __devexit_p(dataflash_remove), + .remove = dataflash_remove, /* FIXME: investigate suspend and resume... */ }; diff --git a/drivers/mtd/devices/slram.c b/drivers/mtd/devices/slram.c index 8f52fc858e48..5a5cd2ace4a6 100644 --- a/drivers/mtd/devices/slram.c +++ b/drivers/mtd/devices/slram.c @@ -240,7 +240,7 @@ static int parse_cmdline(char *devname, char *szstart, char *szlength) if (*(szlength) != '+') { devlength = simple_strtoul(szlength, &buffer, 0); - devlength = handle_unit(devlength, buffer) - devstart; + devlength = handle_unit(devlength, buffer); if (devlength < devstart) goto err_out; diff --git a/drivers/mtd/devices/spear_smi.c b/drivers/mtd/devices/spear_smi.c index dcc3c9511530..2d2c2a5d4d2a 100644 --- a/drivers/mtd/devices/spear_smi.c +++ b/drivers/mtd/devices/spear_smi.c @@ -756,7 +756,7 @@ err_probe: #ifdef CONFIG_OF -static int __devinit spear_smi_probe_config_dt(struct platform_device *pdev, +static int spear_smi_probe_config_dt(struct platform_device *pdev, struct device_node *np) { struct spear_smi_plat_data *pdata = dev_get_platdata(&pdev->dev); @@ -799,7 +799,7 @@ static int __devinit spear_smi_probe_config_dt(struct platform_device *pdev, return 0; } #else -static int __devinit spear_smi_probe_config_dt(struct platform_device *pdev, +static int spear_smi_probe_config_dt(struct platform_device *pdev, struct device_node *np) { return -ENOSYS; @@ -901,7 +901,7 @@ static int spear_smi_setup_banks(struct platform_device *pdev, * and do proper init for any found one. * Returns 0 on success, non zero otherwise */ -static int __devinit spear_smi_probe(struct platform_device *pdev) +static int spear_smi_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; struct spear_smi_plat_data *pdata = NULL; @@ -1016,7 +1016,7 @@ err: * * free all allocations and delete the partitions. */ -static int __devexit spear_smi_remove(struct platform_device *pdev) +static int spear_smi_remove(struct platform_device *pdev) { struct spear_smi *dev; struct spear_snor_flash *flash; @@ -1092,20 +1092,9 @@ static struct platform_driver spear_smi_driver = { #endif }, .probe = spear_smi_probe, - .remove = __devexit_p(spear_smi_remove), + .remove = spear_smi_remove, }; - -static int spear_smi_init(void) -{ - return platform_driver_register(&spear_smi_driver); -} -module_init(spear_smi_init); - -static void spear_smi_exit(void) -{ - platform_driver_unregister(&spear_smi_driver); -} -module_exit(spear_smi_exit); +module_platform_driver(spear_smi_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Ashish Priyadarshi, Shiraz Hashim <shiraz.hashim@st.com>"); diff --git a/drivers/mtd/devices/sst25l.c b/drivers/mtd/devices/sst25l.c index ab8a2f4c8d60..8091b0163694 100644 --- a/drivers/mtd/devices/sst25l.c +++ b/drivers/mtd/devices/sst25l.c @@ -64,7 +64,7 @@ struct flash_info { #define to_sst25l_flash(x) container_of(x, struct sst25l_flash, mtd) -static struct flash_info __devinitdata sst25l_flash_info[] = { +static struct flash_info sst25l_flash_info[] = { {"sst25lf020a", 0xbf43, 256, 1024, 4096}, {"sst25lf040a", 0xbf44, 256, 2048, 4096}, }; @@ -313,7 +313,7 @@ out: return ret; } -static struct flash_info *__devinit sst25l_match_device(struct spi_device *spi) +static struct flash_info *sst25l_match_device(struct spi_device *spi) { struct flash_info *flash_info = NULL; struct spi_message m; @@ -353,7 +353,7 @@ static struct flash_info *__devinit sst25l_match_device(struct spi_device *spi) return flash_info; } -static int __devinit sst25l_probe(struct spi_device *spi) +static int sst25l_probe(struct spi_device *spi) { struct flash_info *flash_info; struct sst25l_flash *flash; @@ -411,7 +411,7 @@ static int __devinit sst25l_probe(struct spi_device *spi) return 0; } -static int __devexit sst25l_remove(struct spi_device *spi) +static int sst25l_remove(struct spi_device *spi) { struct sst25l_flash *flash = dev_get_drvdata(&spi->dev); int ret; @@ -428,7 +428,7 @@ static struct spi_driver sst25l_driver = { .owner = THIS_MODULE, }, .probe = sst25l_probe, - .remove = __devexit_p(sst25l_remove), + .remove = sst25l_remove, }; module_spi_driver(sst25l_driver); diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig index 2e47c2ed0a2d..62ba82c396c2 100644 --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig @@ -324,13 +324,6 @@ config MTD_SOLUTIONENGINE This enables access to the flash chips on the Hitachi SolutionEngine and similar boards. Say 'Y' if you are building a kernel for such a board. -config MTD_CDB89712 - tristate "Cirrus CDB89712 evaluation board mappings" - depends on MTD_CFI && ARCH_CDB89712 - help - This enables access to the flash or ROM chips on the CDB89712 board. - If you have such a board, say 'Y'. - config MTD_SA1100 tristate "CFI Flash device mapped on StrongARM SA11x0" depends on MTD_CFI && ARCH_SA1100 @@ -365,13 +358,6 @@ config MTD_IXP2000 IXP2000 based board and would like to use the flash chips on it, say 'Y'. -config MTD_FORTUNET - tristate "CFI Flash device mapped on the FortuNet board" - depends on MTD_CFI && SA1100_FORTUNET - help - This enables access to the Flash on the FortuNet board. If you - have such a board, say 'Y'. - config MTD_AUTCPU12 bool "NV-RAM mapping AUTCPU12 board" depends on ARCH_AUTCPU12 diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile index deb43e9a1e7f..4ded28711bc1 100644 --- a/drivers/mtd/maps/Makefile +++ b/drivers/mtd/maps/Makefile @@ -7,7 +7,6 @@ obj-$(CONFIG_MTD) += map_funcs.o endif # Chip mappings -obj-$(CONFIG_MTD_CDB89712) += cdb89712.o obj-$(CONFIG_MTD_CFI_FLAGADM) += cfi_flagadm.o obj-$(CONFIG_MTD_DC21285) += dc21285.o obj-$(CONFIG_MTD_DILNETPC) += dilnetpc.o @@ -40,7 +39,6 @@ obj-$(CONFIG_MTD_SOLUTIONENGINE)+= solutionengine.o obj-$(CONFIG_MTD_PCI) += pci.o obj-$(CONFIG_MTD_AUTCPU12) += autcpu12-nvram.o obj-$(CONFIG_MTD_IMPA7) += impa7.o -obj-$(CONFIG_MTD_FORTUNET) += fortunet.o obj-$(CONFIG_MTD_UCLINUX) += uclinux.o obj-$(CONFIG_MTD_NETtel) += nettel.o obj-$(CONFIG_MTD_SCB2_FLASH) += scb2_flash.o diff --git a/drivers/mtd/maps/amd76xrom.c b/drivers/mtd/maps/amd76xrom.c index e2875d6fe129..f7207b0a76dc 100644 --- a/drivers/mtd/maps/amd76xrom.c +++ b/drivers/mtd/maps/amd76xrom.c @@ -100,8 +100,8 @@ static void amd76xrom_cleanup(struct amd76xrom_window *window) } -static int __devinit amd76xrom_init_one (struct pci_dev *pdev, - const struct pci_device_id *ent) +static int amd76xrom_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) { static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL }; u8 byte; @@ -289,7 +289,7 @@ static int __devinit amd76xrom_init_one (struct pci_dev *pdev, } -static void __devexit amd76xrom_remove_one (struct pci_dev *pdev) +static void amd76xrom_remove_one(struct pci_dev *pdev) { struct amd76xrom_window *window = &amd76xrom_window; @@ -347,4 +347,3 @@ module_exit(cleanup_amd76xrom); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Eric Biederman <ebiederman@lnxi.com>"); MODULE_DESCRIPTION("MTD map driver for BIOS chips on the AMD76X southbridge"); - diff --git a/drivers/mtd/maps/autcpu12-nvram.c b/drivers/mtd/maps/autcpu12-nvram.c index 76fb594bb1d9..a2dc2ae4b24e 100644 --- a/drivers/mtd/maps/autcpu12-nvram.c +++ b/drivers/mtd/maps/autcpu12-nvram.c @@ -33,7 +33,7 @@ struct autcpu12_nvram_priv { struct map_info map; }; -static int __devinit autcpu12_nvram_probe(struct platform_device *pdev) +static int autcpu12_nvram_probe(struct platform_device *pdev) { map_word tmp, save0, save1; struct resource *res; @@ -105,7 +105,7 @@ static int __devinit autcpu12_nvram_probe(struct platform_device *pdev) return -ENOMEM; } -static int __devexit autcpu12_nvram_remove(struct platform_device *pdev) +static int autcpu12_nvram_remove(struct platform_device *pdev) { struct autcpu12_nvram_priv *priv = platform_get_drvdata(pdev); @@ -121,7 +121,7 @@ static struct platform_driver autcpu12_nvram_driver = { .owner = THIS_MODULE, }, .probe = autcpu12_nvram_probe, - .remove = __devexit_p(autcpu12_nvram_remove), + .remove = autcpu12_nvram_remove, }; module_platform_driver(autcpu12_nvram_driver); diff --git a/drivers/mtd/maps/bfin-async-flash.c b/drivers/mtd/maps/bfin-async-flash.c index ef5cde84a8b3..f833edfaab79 100644 --- a/drivers/mtd/maps/bfin-async-flash.c +++ b/drivers/mtd/maps/bfin-async-flash.c @@ -30,7 +30,8 @@ #include <linux/io.h> #include <asm/unaligned.h> -#define pr_devinit(fmt, args...) ({ static const __devinitconst char __fmt[] = fmt; printk(__fmt, ## args); }) +#define pr_devinit(fmt, args...) \ + ({ static const char __fmt[] = fmt; printk(__fmt, ## args); }) #define DRIVER_NAME "bfin-async-flash" @@ -123,7 +124,7 @@ static void bfin_flash_copy_to(struct map_info *map, unsigned long to, const voi static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", NULL }; -static int __devinit bfin_flash_probe(struct platform_device *pdev) +static int bfin_flash_probe(struct platform_device *pdev) { int ret; struct physmap_flash_data *pdata = pdev->dev.platform_data; @@ -172,7 +173,7 @@ static int __devinit bfin_flash_probe(struct platform_device *pdev) return 0; } -static int __devexit bfin_flash_remove(struct platform_device *pdev) +static int bfin_flash_remove(struct platform_device *pdev) { struct async_state *state = platform_get_drvdata(pdev); gpio_free(state->enet_flash_pin); @@ -184,7 +185,7 @@ static int __devexit bfin_flash_remove(struct platform_device *pdev) static struct platform_driver bfin_flash_driver = { .probe = bfin_flash_probe, - .remove = __devexit_p(bfin_flash_remove), + .remove = bfin_flash_remove, .driver = { .name = DRIVER_NAME, }, diff --git a/drivers/mtd/maps/cdb89712.c b/drivers/mtd/maps/cdb89712.c deleted file mode 100644 index c29cbf87ea0c..000000000000 --- a/drivers/mtd/maps/cdb89712.c +++ /dev/null @@ -1,278 +0,0 @@ -/* - * Flash on Cirrus CDB89712 - * - */ - -#include <linux/module.h> -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/ioport.h> -#include <linux/init.h> -#include <asm/io.h> -#include <mach/hardware.h> -#include <linux/mtd/mtd.h> -#include <linux/mtd/map.h> -#include <linux/mtd/partitions.h> - -/* dynamic ioremap() areas */ -#define FLASH_START 0x00000000 -#define FLASH_SIZE 0x800000 -#define FLASH_WIDTH 4 - -#define SRAM_START 0x60000000 -#define SRAM_SIZE 0xc000 -#define SRAM_WIDTH 4 - -#define BOOTROM_START 0x70000000 -#define BOOTROM_SIZE 0x80 -#define BOOTROM_WIDTH 4 - - -static struct mtd_info *flash_mtd; - -struct map_info cdb89712_flash_map = { - .name = "flash", - .size = FLASH_SIZE, - .bankwidth = FLASH_WIDTH, - .phys = FLASH_START, -}; - -struct resource cdb89712_flash_resource = { - .name = "Flash", - .start = FLASH_START, - .end = FLASH_START + FLASH_SIZE - 1, - .flags = IORESOURCE_IO | IORESOURCE_BUSY, -}; - -static int __init init_cdb89712_flash (void) -{ - int err; - - if (request_resource (&ioport_resource, &cdb89712_flash_resource)) { - printk(KERN_NOTICE "Failed to reserve Cdb89712 FLASH space\n"); - err = -EBUSY; - goto out; - } - - cdb89712_flash_map.virt = ioremap(FLASH_START, FLASH_SIZE); - if (!cdb89712_flash_map.virt) { - printk(KERN_NOTICE "Failed to ioremap Cdb89712 FLASH space\n"); - err = -EIO; - goto out_resource; - } - simple_map_init(&cdb89712_flash_map); - flash_mtd = do_map_probe("cfi_probe", &cdb89712_flash_map); - if (!flash_mtd) { - flash_mtd = do_map_probe("map_rom", &cdb89712_flash_map); - if (flash_mtd) - flash_mtd->erasesize = 0x10000; - } - if (!flash_mtd) { - printk("FLASH probe failed\n"); - err = -ENXIO; - goto out_ioremap; - } - - flash_mtd->owner = THIS_MODULE; - - if (mtd_device_register(flash_mtd, NULL, 0)) { - printk("FLASH device addition failed\n"); - err = -ENOMEM; - goto out_probe; - } - - return 0; - -out_probe: - map_destroy(flash_mtd); - flash_mtd = 0; -out_ioremap: - iounmap((void *)cdb89712_flash_map.virt); -out_resource: - release_resource (&cdb89712_flash_resource); -out: - return err; -} - - - - - -static struct mtd_info *sram_mtd; - -struct map_info cdb89712_sram_map = { - .name = "SRAM", - .size = SRAM_SIZE, - .bankwidth = SRAM_WIDTH, - .phys = SRAM_START, -}; - -struct resource cdb89712_sram_resource = { - .name = "SRAM", - .start = SRAM_START, - .end = SRAM_START + SRAM_SIZE - 1, - .flags = IORESOURCE_IO | IORESOURCE_BUSY, -}; - -static int __init init_cdb89712_sram (void) -{ - int err; - - if (request_resource (&ioport_resource, &cdb89712_sram_resource)) { - printk(KERN_NOTICE "Failed to reserve Cdb89712 SRAM space\n"); - err = -EBUSY; - goto out; - } - - cdb89712_sram_map.virt = ioremap(SRAM_START, SRAM_SIZE); - if (!cdb89712_sram_map.virt) { - printk(KERN_NOTICE "Failed to ioremap Cdb89712 SRAM space\n"); - err = -EIO; - goto out_resource; - } - simple_map_init(&cdb89712_sram_map); - sram_mtd = do_map_probe("map_ram", &cdb89712_sram_map); - if (!sram_mtd) { - printk("SRAM probe failed\n"); - err = -ENXIO; - goto out_ioremap; - } - - sram_mtd->owner = THIS_MODULE; - sram_mtd->erasesize = 16; - - if (mtd_device_register(sram_mtd, NULL, 0)) { - printk("SRAM device addition failed\n"); - err = -ENOMEM; - goto out_probe; - } - - return 0; - -out_probe: - map_destroy(sram_mtd); - sram_mtd = 0; -out_ioremap: - iounmap((void *)cdb89712_sram_map.virt); -out_resource: - release_resource (&cdb89712_sram_resource); -out: - return err; -} - - - - - - - -static struct mtd_info *bootrom_mtd; - -struct map_info cdb89712_bootrom_map = { - .name = "BootROM", - .size = BOOTROM_SIZE, - .bankwidth = BOOTROM_WIDTH, - .phys = BOOTROM_START, -}; - -struct resource cdb89712_bootrom_resource = { - .name = "BootROM", - .start = BOOTROM_START, - .end = BOOTROM_START + BOOTROM_SIZE - 1, - .flags = IORESOURCE_IO | IORESOURCE_BUSY, -}; - -static int __init init_cdb89712_bootrom (void) -{ - int err; - - if (request_resource (&ioport_resource, &cdb89712_bootrom_resource)) { - printk(KERN_NOTICE "Failed to reserve Cdb89712 BOOTROM space\n"); - err = -EBUSY; - goto out; - } - - cdb89712_bootrom_map.virt = ioremap(BOOTROM_START, BOOTROM_SIZE); - if (!cdb89712_bootrom_map.virt) { - printk(KERN_NOTICE "Failed to ioremap Cdb89712 BootROM space\n"); - err = -EIO; - goto out_resource; - } - simple_map_init(&cdb89712_bootrom_map); - bootrom_mtd = do_map_probe("map_rom", &cdb89712_bootrom_map); - if (!bootrom_mtd) { - printk("BootROM probe failed\n"); - err = -ENXIO; - goto out_ioremap; - } - - bootrom_mtd->owner = THIS_MODULE; - bootrom_mtd->erasesize = 0x10000; - - if (mtd_device_register(bootrom_mtd, NULL, 0)) { - printk("BootROM device addition failed\n"); - err = -ENOMEM; - goto out_probe; - } - - return 0; - -out_probe: - map_destroy(bootrom_mtd); - bootrom_mtd = 0; -out_ioremap: - iounmap((void *)cdb89712_bootrom_map.virt); -out_resource: - release_resource (&cdb89712_bootrom_resource); -out: - return err; -} - - - - - -static int __init init_cdb89712_maps(void) -{ - - printk(KERN_INFO "Cirrus CDB89712 MTD mappings:\n Flash 0x%x at 0x%x\n SRAM 0x%x at 0x%x\n BootROM 0x%x at 0x%x\n", - FLASH_SIZE, FLASH_START, SRAM_SIZE, SRAM_START, BOOTROM_SIZE, BOOTROM_START); - - init_cdb89712_flash(); - init_cdb89712_sram(); - init_cdb89712_bootrom(); - - return 0; -} - - -static void __exit cleanup_cdb89712_maps(void) -{ - if (sram_mtd) { - mtd_device_unregister(sram_mtd); - map_destroy(sram_mtd); - iounmap((void *)cdb89712_sram_map.virt); - release_resource (&cdb89712_sram_resource); - } - - if (flash_mtd) { - mtd_device_unregister(flash_mtd); - map_destroy(flash_mtd); - iounmap((void *)cdb89712_flash_map.virt); - release_resource (&cdb89712_flash_resource); - } - - if (bootrom_mtd) { - mtd_device_unregister(bootrom_mtd); - map_destroy(bootrom_mtd); - iounmap((void *)cdb89712_bootrom_map.virt); - release_resource (&cdb89712_bootrom_resource); - } -} - -module_init(init_cdb89712_maps); -module_exit(cleanup_cdb89712_maps); - -MODULE_AUTHOR("Ray L"); -MODULE_DESCRIPTION("ARM CDB89712 map driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/mtd/maps/ck804xrom.c b/drivers/mtd/maps/ck804xrom.c index 3d0e762fa5f2..586a1c77e48a 100644 --- a/drivers/mtd/maps/ck804xrom.c +++ b/drivers/mtd/maps/ck804xrom.c @@ -112,8 +112,8 @@ static void ck804xrom_cleanup(struct ck804xrom_window *window) } -static int __devinit ck804xrom_init_one (struct pci_dev *pdev, - const struct pci_device_id *ent) +static int ck804xrom_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) { static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL }; u8 byte; @@ -320,7 +320,7 @@ static int __devinit ck804xrom_init_one (struct pci_dev *pdev, } -static void __devexit ck804xrom_remove_one (struct pci_dev *pdev) +static void ck804xrom_remove_one(struct pci_dev *pdev) { struct ck804xrom_window *window = &ck804xrom_window; diff --git a/drivers/mtd/maps/esb2rom.c b/drivers/mtd/maps/esb2rom.c index 08322b1c3e81..ff8681a25831 100644 --- a/drivers/mtd/maps/esb2rom.c +++ b/drivers/mtd/maps/esb2rom.c @@ -144,7 +144,7 @@ static void esb2rom_cleanup(struct esb2rom_window *window) pci_dev_put(window->pdev); } -static int __devinit esb2rom_init_one(struct pci_dev *pdev, +static int esb2rom_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL }; @@ -378,13 +378,13 @@ static int __devinit esb2rom_init_one(struct pci_dev *pdev, return 0; } -static void __devexit esb2rom_remove_one (struct pci_dev *pdev) +static void esb2rom_remove_one(struct pci_dev *pdev) { struct esb2rom_window *window = &esb2rom_window; esb2rom_cleanup(window); } -static struct pci_device_id esb2rom_pci_tbl[] __devinitdata = { +static struct pci_device_id esb2rom_pci_tbl[] = { { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, PCI_ANY_ID, PCI_ANY_ID, }, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, diff --git a/drivers/mtd/maps/fortunet.c b/drivers/mtd/maps/fortunet.c deleted file mode 100644 index 956e2e4f30ea..000000000000 --- a/drivers/mtd/maps/fortunet.c +++ /dev/null @@ -1,277 +0,0 @@ -/* fortunet.c memory map - * - */ - -#include <linux/module.h> -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/string.h> - -#include <linux/mtd/mtd.h> -#include <linux/mtd/map.h> -#include <linux/mtd/partitions.h> - -#include <asm/io.h> - -#define MAX_NUM_REGIONS 4 -#define MAX_NUM_PARTITIONS 8 - -#define DEF_WINDOW_ADDR_PHY 0x00000000 -#define DEF_WINDOW_SIZE 0x00800000 // 8 Mega Bytes - -#define MTD_FORTUNET_PK "MTD FortuNet: " - -#define MAX_NAME_SIZE 128 - -struct map_region -{ - int window_addr_physical; - int altbankwidth; - struct map_info map_info; - struct mtd_info *mymtd; - struct mtd_partition parts[MAX_NUM_PARTITIONS]; - char map_name[MAX_NAME_SIZE]; - char parts_name[MAX_NUM_PARTITIONS][MAX_NAME_SIZE]; -}; - -static struct map_region map_regions[MAX_NUM_REGIONS]; -static int map_regions_set[MAX_NUM_REGIONS] = {0,0,0,0}; -static int map_regions_parts[MAX_NUM_REGIONS] = {0,0,0,0}; - - - -struct map_info default_map = { - .size = DEF_WINDOW_SIZE, - .bankwidth = 4, -}; - -static char * __init get_string_option(char *dest,int dest_size,char *sor) -{ - if(!dest_size) - return sor; - dest_size--; - while(*sor) - { - if(*sor==',') - { - sor++; - break; - } - else if(*sor=='\"') - { - sor++; - while(*sor) - { - if(*sor=='\"') - { - sor++; - break; - } - *dest = *sor; - dest++; - sor++; - dest_size--; - if(!dest_size) - { - *dest = 0; - return sor; - } - } - } - else - { - *dest = *sor; - dest++; - sor++; - dest_size--; - if(!dest_size) - { - *dest = 0; - return sor; - } - } - } - *dest = 0; - return sor; -} - -static int __init MTD_New_Region(char *line) -{ - char string[MAX_NAME_SIZE]; - int params[6]; - get_options (get_string_option(string,sizeof(string),line),6,params); - if(params[0]<1) - { - printk(MTD_FORTUNET_PK "Bad parameters for MTD Region " - " name,region-number[,base,size,bankwidth,altbankwidth]\n"); - return 1; - } - if((params[1]<0)||(params[1]>=MAX_NUM_REGIONS)) - { - printk(MTD_FORTUNET_PK "Bad region index of %d only have 0..%u regions\n", - params[1],MAX_NUM_REGIONS-1); - return 1; - } - memset(&map_regions[params[1]],0,sizeof(map_regions[params[1]])); - memcpy(&map_regions[params[1]].map_info, - &default_map,sizeof(map_regions[params[1]].map_info)); - map_regions_set[params[1]] = 1; - map_regions[params[1]].window_addr_physical = DEF_WINDOW_ADDR_PHY; - map_regions[params[1]].altbankwidth = 2; - map_regions[params[1]].mymtd = NULL; - map_regions[params[1]].map_info.name = map_regions[params[1]].map_name; - strcpy(map_regions[params[1]].map_info.name,string); - if(params[0]>1) - { - map_regions[params[1]].window_addr_physical = params[2]; - } - if(params[0]>2) - { - map_regions[params[1]].map_info.size = params[3]; - } - if(params[0]>3) - { - map_regions[params[1]].map_info.bankwidth = params[4]; - } - if(params[0]>4) - { - map_regions[params[1]].altbankwidth = params[5]; - } - return 1; -} - -static int __init MTD_New_Partition(char *line) -{ - char string[MAX_NAME_SIZE]; - int params[4]; - get_options (get_string_option(string,sizeof(string),line),4,params); - if(params[0]<3) - { - printk(MTD_FORTUNET_PK "Bad parameters for MTD Partition " - " name,region-number,size,offset\n"); - return 1; - } - if((params[1]<0)||(params[1]>=MAX_NUM_REGIONS)) - { - printk(MTD_FORTUNET_PK "Bad region index of %d only have 0..%u regions\n", - params[1],MAX_NUM_REGIONS-1); - return 1; - } - if(map_regions_parts[params[1]]>=MAX_NUM_PARTITIONS) - { - printk(MTD_FORTUNET_PK "Out of space for partition in this region\n"); - return 1; - } - map_regions[params[1]].parts[map_regions_parts[params[1]]].name = - map_regions[params[1]]. parts_name[map_regions_parts[params[1]]]; - strcpy(map_regions[params[1]].parts[map_regions_parts[params[1]]].name,string); - map_regions[params[1]].parts[map_regions_parts[params[1]]].size = - params[2]; - map_regions[params[1]].parts[map_regions_parts[params[1]]].offset = - params[3]; - map_regions[params[1]].parts[map_regions_parts[params[1]]].mask_flags = 0; - map_regions_parts[params[1]]++; - return 1; -} - -__setup("MTD_Region=", MTD_New_Region); -__setup("MTD_Partition=", MTD_New_Partition); - -/* Backwards-spelling-compatibility */ -__setup("MTD_Partion=", MTD_New_Partition); - -static int __init init_fortunet(void) -{ - int ix,iy; - for(iy=ix=0;ix<MAX_NUM_REGIONS;ix++) - { - if(map_regions_parts[ix]&&(!map_regions_set[ix])) - { - printk(MTD_FORTUNET_PK "Region %d is not setup (Setting to default)\n", - ix); - memset(&map_regions[ix],0,sizeof(map_regions[ix])); - memcpy(&map_regions[ix].map_info,&default_map, - sizeof(map_regions[ix].map_info)); - map_regions_set[ix] = 1; - map_regions[ix].window_addr_physical = DEF_WINDOW_ADDR_PHY; - map_regions[ix].altbankwidth = 2; - map_regions[ix].mymtd = NULL; - map_regions[ix].map_info.name = map_regions[ix].map_name; - strcpy(map_regions[ix].map_info.name,"FORTUNET"); - } - if(map_regions_set[ix]) - { - iy++; - printk(KERN_NOTICE MTD_FORTUNET_PK "%s flash device at physically " - " address %x size %x\n", - map_regions[ix].map_info.name, - map_regions[ix].window_addr_physical, - map_regions[ix].map_info.size); - - map_regions[ix].map_info.phys = map_regions[ix].window_addr_physical, - - map_regions[ix].map_info.virt = - ioremap_nocache( - map_regions[ix].window_addr_physical, - map_regions[ix].map_info.size); - if(!map_regions[ix].map_info.virt) - { - int j = 0; - printk(MTD_FORTUNET_PK "%s flash failed to ioremap!\n", - map_regions[ix].map_info.name); - for (j = 0 ; j < ix; j++) - iounmap(map_regions[j].map_info.virt); - return -ENXIO; - } - simple_map_init(&map_regions[ix].map_info); - - printk(KERN_NOTICE MTD_FORTUNET_PK "%s flash is virtually at: %x\n", - map_regions[ix].map_info.name, - map_regions[ix].map_info.virt); - map_regions[ix].mymtd = do_map_probe("cfi_probe", - &map_regions[ix].map_info); - if((!map_regions[ix].mymtd)&&( - map_regions[ix].altbankwidth!=map_regions[ix].map_info.bankwidth)) - { - printk(KERN_NOTICE MTD_FORTUNET_PK "Trying alternate bankwidth " - "for %s flash.\n", - map_regions[ix].map_info.name); - map_regions[ix].map_info.bankwidth = - map_regions[ix].altbankwidth; - map_regions[ix].mymtd = do_map_probe("cfi_probe", - &map_regions[ix].map_info); - } - map_regions[ix].mymtd->owner = THIS_MODULE; - mtd_device_register(map_regions[ix].mymtd, - map_regions[ix].parts, - map_regions_parts[ix]); - } - } - if(iy) - return 0; - return -ENXIO; -} - -static void __exit cleanup_fortunet(void) -{ - int ix; - for(ix=0;ix<MAX_NUM_REGIONS;ix++) - { - if(map_regions_set[ix]) - { - if( map_regions[ix].mymtd ) - { - mtd_device_unregister(map_regions[ix].mymtd); - map_destroy( map_regions[ix].mymtd ); - } - iounmap((void *)map_regions[ix].map_info.virt); - } - } -} - -module_init(init_fortunet); -module_exit(cleanup_fortunet); - -MODULE_AUTHOR("FortuNet, Inc."); -MODULE_DESCRIPTION("MTD map driver for FortuNet boards"); diff --git a/drivers/mtd/maps/gpio-addr-flash.c b/drivers/mtd/maps/gpio-addr-flash.c index e4de96ba52b3..7b643de2500b 100644 --- a/drivers/mtd/maps/gpio-addr-flash.c +++ b/drivers/mtd/maps/gpio-addr-flash.c @@ -26,7 +26,8 @@ #include <linux/slab.h> #include <linux/types.h> -#define pr_devinit(fmt, args...) ({ static const __devinitconst char __fmt[] = fmt; printk(__fmt, ## args); }) +#define pr_devinit(fmt, args...) \ + ({ static const char __fmt[] = fmt; printk(__fmt, ## args); }) #define DRIVER_NAME "gpio-addr-flash" #define PFX DRIVER_NAME ": " @@ -142,7 +143,8 @@ static void gf_write(struct map_info *map, map_word d1, unsigned long ofs) * * See gf_copy_from() caveat. */ -static void gf_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) +static void gf_copy_to(struct map_info *map, unsigned long to, + const void *from, ssize_t len) { struct async_state *state = gf_map_info_to_state(map); @@ -185,7 +187,7 @@ static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", NULL }; * ... * }; */ -static int __devinit gpio_flash_probe(struct platform_device *pdev) +static int gpio_flash_probe(struct platform_device *pdev) { size_t i, arr_size; struct physmap_flash_data *pdata; @@ -258,7 +260,7 @@ static int __devinit gpio_flash_probe(struct platform_device *pdev) return 0; } -static int __devexit gpio_flash_remove(struct platform_device *pdev) +static int gpio_flash_remove(struct platform_device *pdev) { struct async_state *state = platform_get_drvdata(pdev); size_t i = 0; @@ -273,7 +275,7 @@ static int __devexit gpio_flash_remove(struct platform_device *pdev) static struct platform_driver gpio_flash_driver = { .probe = gpio_flash_probe, - .remove = __devexit_p(gpio_flash_remove), + .remove = gpio_flash_remove, .driver = { .name = DRIVER_NAME, }, diff --git a/drivers/mtd/maps/ichxrom.c b/drivers/mtd/maps/ichxrom.c index 6689dcb3124d..c7478e18f485 100644 --- a/drivers/mtd/maps/ichxrom.c +++ b/drivers/mtd/maps/ichxrom.c @@ -84,8 +84,8 @@ static void ichxrom_cleanup(struct ichxrom_window *window) } -static int __devinit ichxrom_init_one (struct pci_dev *pdev, - const struct pci_device_id *ent) +static int ichxrom_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) { static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL }; struct ichxrom_window *window = &ichxrom_window; @@ -315,13 +315,13 @@ static int __devinit ichxrom_init_one (struct pci_dev *pdev, } -static void __devexit ichxrom_remove_one (struct pci_dev *pdev) +static void ichxrom_remove_one(struct pci_dev *pdev) { struct ichxrom_window *window = &ichxrom_window; ichxrom_cleanup(window); } -static struct pci_device_id ichxrom_pci_tbl[] __devinitdata = { +static struct pci_device_id ichxrom_pci_tbl[] = { { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, PCI_ANY_ID, PCI_ANY_ID, }, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, diff --git a/drivers/mtd/maps/intel_vr_nor.c b/drivers/mtd/maps/intel_vr_nor.c index 93f03175c82d..3ee2ad1dcbe7 100644 --- a/drivers/mtd/maps/intel_vr_nor.c +++ b/drivers/mtd/maps/intel_vr_nor.c @@ -63,24 +63,24 @@ struct vr_nor_mtd { #define TIMING_BYTE_EN (1 << 0) /* 8-bit vs 16-bit bus */ #define TIMING_MASK 0x3FFF0000 -static void __devexit vr_nor_destroy_partitions(struct vr_nor_mtd *p) +static void vr_nor_destroy_partitions(struct vr_nor_mtd *p) { mtd_device_unregister(p->info); } -static int __devinit vr_nor_init_partitions(struct vr_nor_mtd *p) +static int 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, NULL, NULL, 0); } -static void __devexit vr_nor_destroy_mtd_setup(struct vr_nor_mtd *p) +static void vr_nor_destroy_mtd_setup(struct vr_nor_mtd *p) { map_destroy(p->info); } -static int __devinit vr_nor_mtd_setup(struct vr_nor_mtd *p) +static int vr_nor_mtd_setup(struct vr_nor_mtd *p) { static const char *probe_types[] = { "cfi_probe", "jedec_probe", NULL }; @@ -96,7 +96,7 @@ static int __devinit vr_nor_mtd_setup(struct vr_nor_mtd *p) return 0; } -static void __devexit vr_nor_destroy_maps(struct vr_nor_mtd *p) +static void vr_nor_destroy_maps(struct vr_nor_mtd *p) { unsigned int exp_timing_cs0; @@ -116,7 +116,7 @@ static void __devexit vr_nor_destroy_maps(struct vr_nor_mtd *p) * Initialize the map_info structure and map the flash. * Returns 0 on success, nonzero otherwise. */ -static int __devinit vr_nor_init_maps(struct vr_nor_mtd *p) +static int vr_nor_init_maps(struct vr_nor_mtd *p) { unsigned long csr_phys, csr_len; unsigned long win_phys, win_len; @@ -176,7 +176,7 @@ static struct pci_device_id vr_nor_pci_ids[] = { {0,} }; -static void __devexit vr_nor_pci_remove(struct pci_dev *dev) +static void vr_nor_pci_remove(struct pci_dev *dev) { struct vr_nor_mtd *p = pci_get_drvdata(dev); @@ -189,7 +189,7 @@ static void __devexit vr_nor_pci_remove(struct pci_dev *dev) pci_disable_device(dev); } -static int __devinit +static int vr_nor_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) { struct vr_nor_mtd *p = NULL; @@ -256,7 +256,7 @@ vr_nor_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) static struct pci_driver vr_nor_pci_driver = { .name = DRV_NAME, .probe = vr_nor_pci_probe, - .remove = __devexit_p(vr_nor_pci_remove), + .remove = vr_nor_pci_remove, .id_table = vr_nor_pci_ids, }; diff --git a/drivers/mtd/maps/lantiq-flash.c b/drivers/mtd/maps/lantiq-flash.c index c03456f17004..3c3c791eb96a 100644 --- a/drivers/mtd/maps/lantiq-flash.c +++ b/drivers/mtd/maps/lantiq-flash.c @@ -45,7 +45,7 @@ struct ltq_mtd { }; static const char ltq_map_name[] = "ltq_nor"; -static const char *ltq_probe_types[] __devinitconst = { +static const char *ltq_probe_types[] = { "cmdlinepart", "ofpart", NULL }; static map_word @@ -109,7 +109,7 @@ ltq_copy_to(struct map_info *map, unsigned long to, spin_unlock_irqrestore(&ebu_lock, flags); } -static int __devinit +static int ltq_mtd_probe(struct platform_device *pdev) { struct mtd_part_parser_data ppdata; @@ -185,7 +185,7 @@ err_out: return err; } -static int __devexit +static int ltq_mtd_remove(struct platform_device *pdev) { struct ltq_mtd *ltq_mtd = platform_get_drvdata(pdev); @@ -209,7 +209,7 @@ MODULE_DEVICE_TABLE(of, ltq_mtd_match); static struct platform_driver ltq_mtd_driver = { .probe = ltq_mtd_probe, - .remove = __devexit_p(ltq_mtd_remove), + .remove = ltq_mtd_remove, .driver = { .name = "ltq-nor", .owner = THIS_MODULE, diff --git a/drivers/mtd/maps/latch-addr-flash.c b/drivers/mtd/maps/latch-addr-flash.c index 3c7ad17fca78..ab0fead56b83 100644 --- a/drivers/mtd/maps/latch-addr-flash.c +++ b/drivers/mtd/maps/latch-addr-flash.c @@ -125,7 +125,7 @@ static int latch_addr_flash_remove(struct platform_device *dev) return 0; } -static int __devinit latch_addr_flash_probe(struct platform_device *dev) +static int latch_addr_flash_probe(struct platform_device *dev) { struct latch_addr_flash_data *latch_addr_data; struct latch_addr_flash_info *info; @@ -218,7 +218,7 @@ done: static struct platform_driver latch_addr_flash_driver = { .probe = latch_addr_flash_probe, - .remove = __devexit_p(latch_addr_flash_remove), + .remove = latch_addr_flash_remove, .driver = { .name = DRIVER_NAME, }, diff --git a/drivers/mtd/maps/pci.c b/drivers/mtd/maps/pci.c index 1c30c1a307f4..ed82914966f5 100644 --- a/drivers/mtd/maps/pci.c +++ b/drivers/mtd/maps/pci.c @@ -253,7 +253,7 @@ static struct pci_device_id mtd_pci_ids[] = { * Generic code follows. */ -static int __devinit +static int mtd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) { struct mtd_pci_info *info = (struct mtd_pci_info *)id->driver_data; @@ -308,7 +308,7 @@ out: return err; } -static void __devexit +static void mtd_pci_remove(struct pci_dev *dev) { struct mtd_info *mtd = pci_get_drvdata(dev); @@ -326,7 +326,7 @@ mtd_pci_remove(struct pci_dev *dev) static struct pci_driver mtd_pci_driver = { .name = "MTD PCI", .probe = mtd_pci_probe, - .remove = __devexit_p(mtd_pci_remove), + .remove = mtd_pci_remove, .id_table = mtd_pci_ids, }; diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c index 6f19acadb06c..37cdc201652f 100644 --- a/drivers/mtd/maps/physmap_of.c +++ b/drivers/mtd/maps/physmap_of.c @@ -77,7 +77,7 @@ static int of_flash_remove(struct platform_device *dev) /* Helper function to handle probing of the obsolete "direct-mapped" * compatible binding, which has an extra "probe-type" property * describing the type of flash probe necessary. */ -static struct mtd_info * __devinit obsolete_probe(struct platform_device *dev, +static struct mtd_info *obsolete_probe(struct platform_device *dev, struct map_info *map) { struct device_node *dp = dev->dev.of_node; @@ -116,7 +116,7 @@ static struct mtd_info * __devinit obsolete_probe(struct platform_device *dev, information. */ static const char *part_probe_types_def[] = { "cmdlinepart", "RedBoot", "ofpart", "ofoldpart", NULL }; -static const char ** __devinit of_get_probes(struct device_node *dp) +static const char **of_get_probes(struct device_node *dp) { const char *cp; int cplen; @@ -145,14 +145,14 @@ static const char ** __devinit of_get_probes(struct device_node *dp) return res; } -static void __devinit of_free_probes(const char **probes) +static void of_free_probes(const char **probes) { if (probes != part_probe_types_def) kfree(probes); } static struct of_device_id of_flash_match[]; -static int __devinit of_flash_probe(struct platform_device *dev) +static int of_flash_probe(struct platform_device *dev) { const char **part_probe_types; const struct of_device_id *match; @@ -170,6 +170,7 @@ static int __devinit of_flash_probe(struct platform_device *dev) resource_size_t res_size; struct mtd_part_parser_data ppdata; bool map_indirect; + const char *mtd_name; match = of_match_device(of_flash_match, &dev->dev); if (!match) @@ -178,6 +179,8 @@ static int __devinit of_flash_probe(struct platform_device *dev) reg_tuple_size = (of_n_addr_cells(dp) + of_n_size_cells(dp)) * sizeof(u32); + of_property_read_string(dp, "linux,mtd-name", &mtd_name); + /* * Get number of "reg" tuples. Scan for MTD devices on area's * described by each "reg" region. This makes it possible (including @@ -234,7 +237,7 @@ static int __devinit of_flash_probe(struct platform_device *dev) goto err_out; } - info->list[i].map.name = dev_name(&dev->dev); + info->list[i].map.name = mtd_name ?: dev_name(&dev->dev); info->list[i].map.phys = res.start; info->list[i].map.size = res_size; info->list[i].map.bankwidth = be32_to_cpup(width); @@ -282,6 +285,7 @@ static int __devinit of_flash_probe(struct platform_device *dev) } err = 0; + info->cmtd = NULL; if (info->list_size == 1) { info->cmtd = info->list[0].mtd; } else if (info->list_size > 1) { @@ -290,9 +294,10 @@ static int __devinit of_flash_probe(struct platform_device *dev) */ info->cmtd = mtd_concat_create(mtd_list, info->list_size, dev_name(&dev->dev)); - if (info->cmtd == NULL) - err = -ENXIO; } + if (info->cmtd == NULL) + err = -ENXIO; + if (err) goto err_out; diff --git a/drivers/mtd/maps/pismo.c b/drivers/mtd/maps/pismo.c index 65bd1cd4d627..afea93b515d5 100644 --- a/drivers/mtd/maps/pismo.c +++ b/drivers/mtd/maps/pismo.c @@ -58,7 +58,7 @@ static void pismo_set_vpp(struct platform_device *pdev, int on) pismo->vpp(pismo->vpp_data, on); } -static unsigned int __devinit pismo_width_to_bytes(unsigned int width) +static unsigned int pismo_width_to_bytes(unsigned int width) { width &= 15; if (width > 2) @@ -66,7 +66,7 @@ static unsigned int __devinit pismo_width_to_bytes(unsigned int width) return 1 << width; } -static int __devinit pismo_eeprom_read(struct i2c_client *client, void *buf, +static int pismo_eeprom_read(struct i2c_client *client, void *buf, u8 addr, size_t size) { int ret; @@ -88,7 +88,7 @@ static int __devinit pismo_eeprom_read(struct i2c_client *client, void *buf, return ret == ARRAY_SIZE(msg) ? size : -EIO; } -static int __devinit pismo_add_device(struct pismo_data *pismo, int i, +static int pismo_add_device(struct pismo_data *pismo, int i, struct pismo_mem *region, const char *name, void *pdata, size_t psize) { struct platform_device *dev; @@ -129,7 +129,7 @@ static int __devinit pismo_add_device(struct pismo_data *pismo, int i, return ret; } -static int __devinit pismo_add_nor(struct pismo_data *pismo, int i, +static int pismo_add_nor(struct pismo_data *pismo, int i, struct pismo_mem *region) { struct physmap_flash_data data = { @@ -143,7 +143,7 @@ static int __devinit pismo_add_nor(struct pismo_data *pismo, int i, &data, sizeof(data)); } -static int __devinit pismo_add_sram(struct pismo_data *pismo, int i, +static int pismo_add_sram(struct pismo_data *pismo, int i, struct pismo_mem *region) { struct platdata_mtd_ram data = { @@ -154,7 +154,7 @@ static int __devinit pismo_add_sram(struct pismo_data *pismo, int i, &data, sizeof(data)); } -static void __devinit pismo_add_one(struct pismo_data *pismo, int i, +static void pismo_add_one(struct pismo_data *pismo, int i, const struct pismo_cs_block *cs, phys_addr_t base) { struct device *dev = &pismo->client->dev; @@ -197,7 +197,7 @@ static void __devinit pismo_add_one(struct pismo_data *pismo, int i, } } -static int __devexit pismo_remove(struct i2c_client *client) +static int pismo_remove(struct i2c_client *client) { struct pismo_data *pismo = i2c_get_clientdata(client); int i; @@ -210,7 +210,7 @@ static int __devexit pismo_remove(struct i2c_client *client) return 0; } -static int __devinit pismo_probe(struct i2c_client *client, +static int pismo_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); @@ -267,7 +267,7 @@ static struct i2c_driver pismo_driver = { .owner = THIS_MODULE, }, .probe = pismo_probe, - .remove = __devexit_p(pismo_remove), + .remove = pismo_remove, .id_table = pismo_id, }; diff --git a/drivers/mtd/maps/plat-ram.c b/drivers/mtd/maps/plat-ram.c index 891558de3ec1..2de66b062f0d 100644 --- a/drivers/mtd/maps/plat-ram.c +++ b/drivers/mtd/maps/plat-ram.c @@ -219,7 +219,7 @@ static int platram_probe(struct platform_device *pdev) platram_setrw(info, PLATRAM_RW); - /* check to see if there are any available partitions, or wether + /* check to see if there are any available partitions, or whether * to add this device whole */ err = mtd_device_parse_register(info->mtd, pdata->probes, NULL, diff --git a/drivers/mtd/maps/pxa2xx-flash.c b/drivers/mtd/maps/pxa2xx-flash.c index 81884c277405..43e3dbb976d9 100644 --- a/drivers/mtd/maps/pxa2xx-flash.c +++ b/drivers/mtd/maps/pxa2xx-flash.c @@ -49,7 +49,7 @@ struct pxa2xx_flash_info { static const char *probes[] = { "RedBoot", "cmdlinepart", NULL }; -static int __devinit pxa2xx_flash_probe(struct platform_device *pdev) +static int pxa2xx_flash_probe(struct platform_device *pdev) { struct flash_platform_data *flash = pdev->dev.platform_data; struct pxa2xx_flash_info *info; @@ -105,7 +105,7 @@ static int __devinit pxa2xx_flash_probe(struct platform_device *pdev) return 0; } -static int __devexit pxa2xx_flash_remove(struct platform_device *dev) +static int pxa2xx_flash_remove(struct platform_device *dev) { struct pxa2xx_flash_info *info = platform_get_drvdata(dev); @@ -139,7 +139,7 @@ static struct platform_driver pxa2xx_flash_driver = { .owner = THIS_MODULE, }, .probe = pxa2xx_flash_probe, - .remove = __devexit_p(pxa2xx_flash_remove), + .remove = pxa2xx_flash_remove, .shutdown = pxa2xx_flash_shutdown, }; diff --git a/drivers/mtd/maps/sa1100-flash.c b/drivers/mtd/maps/sa1100-flash.c index a675bdbcb0fe..f694417cf7e6 100644 --- a/drivers/mtd/maps/sa1100-flash.c +++ b/drivers/mtd/maps/sa1100-flash.c @@ -149,8 +149,8 @@ static void sa1100_destroy(struct sa_info *info, struct flash_platform_data *pla plat->exit(); } -static struct sa_info *__devinit -sa1100_setup_mtd(struct platform_device *pdev, struct flash_platform_data *plat) +static struct sa_info *sa1100_setup_mtd(struct platform_device *pdev, + struct flash_platform_data *plat) { struct sa_info *info; int nr, size, i, ret = 0; @@ -246,7 +246,7 @@ sa1100_setup_mtd(struct platform_device *pdev, struct flash_platform_data *plat) static const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL }; -static int __devinit sa1100_mtd_probe(struct platform_device *pdev) +static int sa1100_mtd_probe(struct platform_device *pdev) { struct flash_platform_data *plat = pdev->dev.platform_data; struct sa_info *info; diff --git a/drivers/mtd/maps/scb2_flash.c b/drivers/mtd/maps/scb2_flash.c index 9dcbc684abdb..71796137e97b 100644 --- a/drivers/mtd/maps/scb2_flash.c +++ b/drivers/mtd/maps/scb2_flash.c @@ -69,7 +69,7 @@ static struct map_info scb2_map = { }; static int region_fail; -static int __devinit +static int scb2_fixup_mtd(struct mtd_info *mtd) { int i; @@ -133,7 +133,7 @@ scb2_fixup_mtd(struct mtd_info *mtd) /* CSB5's 'Function Control Register' has bits for decoding @ >= 0xffc00000 */ #define CSB5_FCR 0x41 #define CSB5_FCR_DECODE_ALL 0x0e -static int __devinit +static int scb2_flash_probe(struct pci_dev *dev, const struct pci_device_id *ent) { u8 reg; @@ -197,7 +197,7 @@ scb2_flash_probe(struct pci_dev *dev, const struct pci_device_id *ent) return 0; } -static void __devexit +static void scb2_flash_remove(struct pci_dev *dev) { if (!scb2_mtd) @@ -231,7 +231,7 @@ static struct pci_driver scb2_flash_driver = { .name = "Intel SCB2 BIOS Flash", .id_table = scb2_flash_pci_ids, .probe = scb2_flash_probe, - .remove = __devexit_p(scb2_flash_remove), + .remove = scb2_flash_remove, }; module_pci_driver(scb2_flash_driver); diff --git a/drivers/mtd/maps/sun_uflash.c b/drivers/mtd/maps/sun_uflash.c index 175e537b444f..d467f3b11c96 100644 --- a/drivers/mtd/maps/sun_uflash.c +++ b/drivers/mtd/maps/sun_uflash.c @@ -108,7 +108,7 @@ int uflash_devinit(struct platform_device *op, struct device_node *dp) return 0; } -static int __devinit uflash_probe(struct platform_device *op) +static int uflash_probe(struct platform_device *op) { struct device_node *dp = op->dev.of_node; @@ -121,7 +121,7 @@ static int __devinit uflash_probe(struct platform_device *op) return uflash_devinit(op, dp); } -static int __devexit uflash_remove(struct platform_device *op) +static int uflash_remove(struct platform_device *op) { struct uflash_dev *up = dev_get_drvdata(&op->dev); @@ -155,7 +155,7 @@ static struct platform_driver uflash_driver = { .of_match_table = uflash_match, }, .probe = uflash_probe, - .remove = __devexit_p(uflash_remove), + .remove = uflash_remove, }; module_platform_driver(uflash_driver); diff --git a/drivers/mtd/maps/vmu-flash.c b/drivers/mtd/maps/vmu-flash.c index 2e2b0945edc7..6b223cfe92b7 100644 --- a/drivers/mtd/maps/vmu-flash.c +++ b/drivers/mtd/maps/vmu-flash.c @@ -596,7 +596,7 @@ fail_name: } /* Handles very basic info about the flash, queries for details */ -static int __devinit vmu_connect(struct maple_device *mdev) +static int vmu_connect(struct maple_device *mdev) { unsigned long test_flash_data, basic_flash_data; int c, error; @@ -690,7 +690,7 @@ fail_nomem: return error; } -static void __devexit vmu_disconnect(struct maple_device *mdev) +static void vmu_disconnect(struct maple_device *mdev) { struct memcard *card; struct mdev_part *mpart; @@ -772,7 +772,7 @@ static void vmu_file_error(struct maple_device *mdev, void *recvbuf) } -static int __devinit probe_maple_vmu(struct device *dev) +static int probe_maple_vmu(struct device *dev) { int error; struct maple_device *mdev = to_maple_dev(dev); @@ -789,7 +789,7 @@ static int __devinit probe_maple_vmu(struct device *dev) return 0; } -static int __devexit remove_maple_vmu(struct device *dev) +static int remove_maple_vmu(struct device *dev) { struct maple_device *mdev = to_maple_dev(dev); @@ -802,7 +802,7 @@ static struct maple_driver vmu_flash_driver = { .drv = { .name = "Dreamcast_visual_memory", .probe = probe_maple_vmu, - .remove = __devexit_p(remove_maple_vmu), + .remove = remove_maple_vmu, }, }; diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c index f1f06715d4e0..5ad39bb5ab4c 100644 --- a/drivers/mtd/mtd_blkdevs.c +++ b/drivers/mtd/mtd_blkdevs.c @@ -32,7 +32,6 @@ #include <linux/hdreg.h> #include <linux/init.h> #include <linux/mutex.h> -#include <linux/kthread.h> #include <asm/uaccess.h> #include "mtdcore.h" @@ -121,16 +120,14 @@ static int do_blktrans_request(struct mtd_blktrans_ops *tr, int mtd_blktrans_cease_background(struct mtd_blktrans_dev *dev) { - if (kthread_should_stop()) - return 1; - return dev->bg_stop; } EXPORT_SYMBOL_GPL(mtd_blktrans_cease_background); -static int mtd_blktrans_thread(void *arg) +static void mtd_blktrans_work(struct work_struct *work) { - struct mtd_blktrans_dev *dev = arg; + struct mtd_blktrans_dev *dev = + container_of(work, struct mtd_blktrans_dev, work); struct mtd_blktrans_ops *tr = dev->tr; struct request_queue *rq = dev->rq; struct request *req = NULL; @@ -138,7 +135,7 @@ static int mtd_blktrans_thread(void *arg) spin_lock_irq(rq->queue_lock); - while (!kthread_should_stop()) { + while (1) { int res; dev->bg_stop = false; @@ -156,15 +153,7 @@ static int mtd_blktrans_thread(void *arg) background_done = !dev->bg_stop; continue; } - set_current_state(TASK_INTERRUPTIBLE); - - if (kthread_should_stop()) - set_current_state(TASK_RUNNING); - - spin_unlock_irq(rq->queue_lock); - schedule(); - spin_lock_irq(rq->queue_lock); - continue; + break; } spin_unlock_irq(rq->queue_lock); @@ -185,8 +174,6 @@ static int mtd_blktrans_thread(void *arg) __blk_end_request_all(req, -EIO); spin_unlock_irq(rq->queue_lock); - - return 0; } static void mtd_blktrans_request(struct request_queue *rq) @@ -199,10 +186,8 @@ static void mtd_blktrans_request(struct request_queue *rq) if (!dev) while ((req = blk_fetch_request(rq)) != NULL) __blk_end_request_all(req, -ENODEV); - else { - dev->bg_stop = true; - wake_up_process(dev->thread); - } + else + queue_work(dev->wq, &dev->work); } static int blktrans_open(struct block_device *bdev, fmode_t mode) @@ -325,7 +310,7 @@ unlock: return ret; } -static const struct block_device_operations mtd_blktrans_ops = { +static const struct block_device_operations mtd_block_ops = { .owner = THIS_MODULE, .open = blktrans_open, .release = blktrans_release, @@ -401,7 +386,7 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) gd->private_data = new; gd->major = tr->major; gd->first_minor = (new->devnum) << tr->part_bits; - gd->fops = &mtd_blktrans_ops; + gd->fops = &mtd_block_ops; if (tr->part_bits) if (new->devnum < 26) @@ -437,14 +422,13 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) gd->queue = new->rq; - /* Create processing thread */ - /* TODO: workqueue ? */ - new->thread = kthread_run(mtd_blktrans_thread, new, - "%s%d", tr->name, new->mtd->index); - if (IS_ERR(new->thread)) { - ret = PTR_ERR(new->thread); + /* Create processing workqueue */ + new->wq = alloc_workqueue("%s%d", 0, 0, + tr->name, new->mtd->index); + if (!new->wq) goto error4; - } + INIT_WORK(&new->work, mtd_blktrans_work); + gd->driverfs_dev = &new->mtd->dev; if (new->readonly) @@ -484,9 +468,8 @@ int del_mtd_blktrans_dev(struct mtd_blktrans_dev *old) /* Stop new requests to arrive */ del_gendisk(old->disk); - - /* Stop the thread */ - kthread_stop(old->thread); + /* Stop workqueue. This will perform any pending request. */ + destroy_workqueue(old->wq); /* Kill current requests */ spin_lock_irqsave(&old->queue_lock, flags); diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index 374c46dff7dd..ec794a72975d 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c @@ -1077,7 +1077,8 @@ EXPORT_SYMBOL_GPL(mtd_writev); * until the request succeeds or until the allocation size falls below * the system page size. This attempts to make sure it does not adversely * impact system performance, so when allocating more than one page, we - * ask the memory allocator to avoid re-trying. + * ask the memory allocator to avoid re-trying, swapping, writing back + * or performing I/O. * * Note, this function also makes sure that the allocated buffer is aligned to * the MTD device's min. I/O unit, i.e. the "mtd->writesize" value. @@ -1091,7 +1092,8 @@ EXPORT_SYMBOL_GPL(mtd_writev); */ void *mtd_kmalloc_up_to(const struct mtd_info *mtd, size_t *size) { - gfp_t flags = __GFP_NOWARN | __GFP_WAIT | __GFP_NORETRY; + gfp_t flags = __GFP_NOWARN | __GFP_WAIT | + __GFP_NORETRY | __GFP_NO_KSWAPD; size_t min_alloc = max_t(size_t, mtd->writesize, PAGE_SIZE); void *kbuf; diff --git a/drivers/mtd/mtdoops.c b/drivers/mtd/mtdoops.c index f5b3f91fa1cc..97bb8f6304d4 100644 --- a/drivers/mtd/mtdoops.c +++ b/drivers/mtd/mtdoops.c @@ -271,7 +271,7 @@ static void find_next_position(struct mtdoops_context *cxt) if (count[0] == 0xffffffff && count[1] == 0xffffffff) mark_page_unused(cxt, page); - if (count[0] == 0xffffffff) + if (count[0] == 0xffffffff || count[1] != MTDOOPS_KERNMSG_MAGIC) continue; if (maxcount == 0xffffffff) { maxcount = count[0]; @@ -289,14 +289,13 @@ static void find_next_position(struct mtdoops_context *cxt) } } if (maxcount == 0xffffffff) { - cxt->nextpage = 0; - cxt->nextcount = 1; - schedule_work(&cxt->work_erase); - return; + cxt->nextpage = cxt->oops_pages - 1; + cxt->nextcount = 0; + } + else { + cxt->nextpage = maxpos; + cxt->nextcount = maxcount; } - - cxt->nextpage = maxpos; - cxt->nextcount = maxcount; mtdoops_inc_counter(cxt); } diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 4883139460be..5819eb575210 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -49,24 +49,31 @@ config MTD_NAND_MUSEUM_IDS NAND chips (page size 256 byte, erase size 4-8KiB). The IDs of these chips were reused by later, larger chips. -config MTD_NAND_AUTCPU12 - tristate "SmartMediaCard on autronix autcpu12 board" - depends on ARCH_AUTCPU12 - help - This enables the driver for the autronix autcpu12 board to - access the SmartMediaCard. - config MTD_NAND_DENALI - depends on PCI + tristate "Support Denali NAND controller" + help + Enable support for the Denali NAND controller. This should be + combined with either the PCI or platform drivers to provide device + registration. + +config MTD_NAND_DENALI_PCI tristate "Support Denali NAND controller on Intel Moorestown" + depends on PCI && MTD_NAND_DENALI help Enable the driver for NAND flash on Intel Moorestown, using the Denali NAND controller core. - + +config MTD_NAND_DENALI_DT + tristate "Support Denali NAND controller as a DT device" + depends on HAVE_CLK && MTD_NAND_DENALI + help + Enable the driver for NAND flash on platforms using a Denali NAND + controller as a DT device. + config MTD_NAND_DENALI_SCRATCH_REG_ADDR hex "Denali NAND size scratch register address" default "0xFF108018" - depends on MTD_NAND_DENALI + depends on MTD_NAND_DENALI_PCI help Some platforms place the NAND chip size in a scratch register because (some versions of) the driver aren't able to automatically @@ -86,12 +93,6 @@ config MTD_NAND_GPIO help This enables a GPIO based NAND flash driver. -config MTD_NAND_SPIA - tristate "NAND Flash device on SPIA board" - depends on ARCH_P720T - help - If you had to ask, you don't have one. Say 'N'. - config MTD_NAND_AMS_DELTA tristate "NAND Flash device on Amstrad E3" depends on MACH_AMS_DELTA @@ -446,6 +447,14 @@ config MTD_NAND_GPMI_NAND block, such as SD card. So pay attention to it when you enable the GPMI. +config MTD_NAND_BCM47XXNFLASH + tristate "Support for NAND flash on BCM4706 BCMA bus" + depends on BCMA_NFLASH + help + BCMA bus can have various flash memories attached, they are + registered by bcma as platform devices. This enables driver for + NAND flash memories. For now only BCM4706 is supported. + config MTD_NAND_PLATFORM tristate "Support for generic platform NAND driver" depends on HAS_IOMEM @@ -512,12 +521,6 @@ config MTD_NAND_MXC This enables the driver for the NAND flash controller on the MXC processors. -config MTD_NAND_NOMADIK - tristate "ST Nomadik 8815 NAND support" - depends on ARCH_NOMADIK - help - Driver for the NAND flash controller on the Nomadik, with ECC. - config MTD_NAND_SH_FLCTL tristate "Support for NAND on Renesas SuperH FLCTL" depends on SUPERH || ARCH_SHMOBILE @@ -559,7 +562,7 @@ config MTD_NAND_JZ4740 config MTD_NAND_FSMC tristate "Support for NAND on ST Micros FSMC" - depends on PLAT_SPEAR || PLAT_NOMADIK || MACH_U300 + depends on PLAT_SPEAR || ARCH_NOMADIK || ARCH_U8500 || MACH_U300 help Enables support for NAND Flash chips on the ST Microelectronics Flexible Static Memory Controller (FSMC) diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index 2cbd0916b733..d76d91205691 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile @@ -9,10 +9,10 @@ obj-$(CONFIG_MTD_NAND_IDS) += nand_ids.o obj-$(CONFIG_MTD_SM_COMMON) += sm_common.o obj-$(CONFIG_MTD_NAND_CAFE) += cafe_nand.o -obj-$(CONFIG_MTD_NAND_SPIA) += spia.o obj-$(CONFIG_MTD_NAND_AMS_DELTA) += ams-delta.o -obj-$(CONFIG_MTD_NAND_AUTCPU12) += autcpu12.o obj-$(CONFIG_MTD_NAND_DENALI) += denali.o +obj-$(CONFIG_MTD_NAND_DENALI_PCI) += denali_pci.o +obj-$(CONFIG_MTD_NAND_DENALI_DT) += denali_dt.o obj-$(CONFIG_MTD_NAND_AU1550) += au1550nd.o obj-$(CONFIG_MTD_NAND_BF5XX) += bf5xx_nand.o obj-$(CONFIG_MTD_NAND_PPCHAMELEONEVB) += ppchameleonevb.o @@ -47,11 +47,11 @@ obj-$(CONFIG_MTD_NAND_MXC) += mxc_nand.o obj-$(CONFIG_MTD_NAND_SOCRATES) += socrates_nand.o obj-$(CONFIG_MTD_NAND_TXX9NDFMC) += txx9ndfmc.o obj-$(CONFIG_MTD_NAND_NUC900) += nuc900_nand.o -obj-$(CONFIG_MTD_NAND_NOMADIK) += nomadik_nand.o obj-$(CONFIG_MTD_NAND_MPC5121_NFC) += mpc5121_nfc.o obj-$(CONFIG_MTD_NAND_RICOH) += r852.o obj-$(CONFIG_MTD_NAND_JZ4740) += jz4740_nand.o obj-$(CONFIG_MTD_NAND_GPMI_NAND) += gpmi-nand/ obj-$(CONFIG_MTD_NAND_XWAY) += xway_nand.o +obj-$(CONFIG_MTD_NAND_BCM47XXNFLASH) += bcm47xxnflash/ nand-objs := nand_base.o nand_bbt.o diff --git a/drivers/mtd/nand/ams-delta.c b/drivers/mtd/nand/ams-delta.c index 9e7723aa7acc..f1d71cdc8aac 100644 --- a/drivers/mtd/nand/ams-delta.c +++ b/drivers/mtd/nand/ams-delta.c @@ -173,7 +173,7 @@ static const struct gpio _mandatory_gpio[] = { /* * Main initialization routine */ -static int __devinit ams_delta_init(struct platform_device *pdev) +static int ams_delta_init(struct platform_device *pdev) { struct nand_chip *this; struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -270,7 +270,7 @@ out_free: /* * Clean up routine */ -static int __devexit ams_delta_cleanup(struct platform_device *pdev) +static int ams_delta_cleanup(struct platform_device *pdev) { void __iomem *io_base = platform_get_drvdata(pdev); @@ -289,7 +289,7 @@ static int __devexit ams_delta_cleanup(struct platform_device *pdev) static struct platform_driver ams_delta_nand_driver = { .probe = ams_delta_init, - .remove = __devexit_p(ams_delta_cleanup), + .remove = ams_delta_cleanup, .driver = { .name = "ams-delta-nand", .owner = THIS_MODULE, diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index 914455783302..90bdca61c797 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -41,6 +41,7 @@ #include <linux/gpio.h> #include <linux/io.h> #include <linux/platform_data/atmel.h> +#include <linux/pinctrl/consumer.h> #include <mach/cpu.h> @@ -330,13 +331,13 @@ static void atmel_write_buf(struct mtd_info *mtd, const u8 *buf, int len) * 12-bits 20-bytes 21-bytes * 24-bits 39-bytes 42-bytes */ -static int __devinit pmecc_get_ecc_bytes(int cap, int sector_size) +static int pmecc_get_ecc_bytes(int cap, int sector_size) { int m = 12 + sector_size / 512; return (m * cap + 7) / 8; } -static void __devinit pmecc_config_ecc_layout(struct nand_ecclayout *layout, +static void pmecc_config_ecc_layout(struct nand_ecclayout *layout, int oobsize, int ecc_len) { int i; @@ -352,7 +353,7 @@ static void __devinit pmecc_config_ecc_layout(struct nand_ecclayout *layout, oobsize - ecc_len - layout->oobfree[0].offset; } -static void __devinit __iomem *pmecc_get_alpha_to(struct atmel_nand_host *host) +static void __iomem *pmecc_get_alpha_to(struct atmel_nand_host *host) { int table_size; @@ -374,7 +375,7 @@ static void pmecc_data_free(struct atmel_nand_host *host) kfree(host->pmecc_delta); } -static int __devinit pmecc_data_alloc(struct atmel_nand_host *host) +static int pmecc_data_alloc(struct atmel_nand_host *host) { const int cap = host->pmecc_corr_cap; @@ -723,6 +724,7 @@ static int pmecc_correction(struct mtd_info *mtd, u32 pmecc_stat, uint8_t *buf, struct atmel_nand_host *host = nand_chip->priv; int i, err_nbr, eccbytes; uint8_t *buf_pos; + int total_err = 0; eccbytes = nand_chip->ecc.bytes; for (i = 0; i < eccbytes; i++) @@ -750,12 +752,13 @@ normal_check: pmecc_correct_data(mtd, buf_pos, ecc, i, host->pmecc_bytes_per_sector, err_nbr); mtd->ecc_stats.corrected += err_nbr; + total_err += err_nbr; } } pmecc_stat >>= 1; } - return 0; + return total_err; } static int atmel_nand_pmecc_read_page(struct mtd_info *mtd, @@ -767,6 +770,7 @@ static int atmel_nand_pmecc_read_page(struct mtd_info *mtd, uint32_t *eccpos = chip->ecc.layout->eccpos; uint32_t stat; unsigned long end_time; + int bitflips = 0; pmecc_writel(host->ecc, CTRL, PMECC_CTRL_RST); pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DISABLE); @@ -789,11 +793,14 @@ static int atmel_nand_pmecc_read_page(struct mtd_info *mtd, } stat = pmecc_readl_relaxed(host->ecc, ISR); - if (stat != 0) - if (pmecc_correction(mtd, stat, buf, &oob[eccpos[0]]) != 0) - return -EIO; + if (stat != 0) { + bitflips = pmecc_correction(mtd, stat, buf, &oob[eccpos[0]]); + if (bitflips < 0) + /* uncorrectable errors */ + return 0; + } - return 0; + return bitflips; } static int atmel_nand_pmecc_write_page(struct mtd_info *mtd, @@ -1205,7 +1212,7 @@ static void atmel_nand_hwctl(struct mtd_info *mtd, int mode) } #if defined(CONFIG_OF) -static int __devinit atmel_of_init_port(struct atmel_nand_host *host, +static int atmel_of_init_port(struct atmel_nand_host *host, struct device_node *np) { u32 val, table_offset; @@ -1292,7 +1299,7 @@ static int __devinit atmel_of_init_port(struct atmel_nand_host *host, return 0; } #else -static int __devinit atmel_of_init_port(struct atmel_nand_host *host, +static int atmel_of_init_port(struct atmel_nand_host *host, struct device_node *np) { return -EINVAL; @@ -1370,6 +1377,7 @@ static int __init atmel_nand_probe(struct platform_device *pdev) struct resource *mem; struct mtd_part_parser_data ppdata = {}; int res; + struct pinctrl *pinctrl; mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!mem) { @@ -1414,6 +1422,13 @@ static int __init atmel_nand_probe(struct platform_device *pdev) nand_chip->IO_ADDR_W = host->io_base; nand_chip->cmd_ctrl = atmel_nand_cmd_ctrl; + pinctrl = devm_pinctrl_get_select_default(&pdev->dev); + if (IS_ERR(pinctrl)) { + dev_err(host->dev, "Failed to request pinctrl\n"); + res = PTR_ERR(pinctrl); + goto err_ecc_ioremap; + } + if (gpio_is_valid(host->board.rdy_pin)) { res = gpio_request(host->board.rdy_pin, "nand_rdy"); if (res < 0) { diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/au1550nd.c index 5c47b200045a..217459d02b2f 100644 --- a/drivers/mtd/nand/au1550nd.c +++ b/drivers/mtd/nand/au1550nd.c @@ -382,7 +382,7 @@ static void au1550_command(struct mtd_info *mtd, unsigned command, int column, i while(!this->dev_ready(mtd)); } -static int __devinit find_nand_cs(unsigned long nand_base) +static int find_nand_cs(unsigned long nand_base) { void __iomem *base = (void __iomem *)KSEG1ADDR(AU1000_STATIC_MEM_PHYS_ADDR); @@ -403,7 +403,7 @@ static int __devinit find_nand_cs(unsigned long nand_base) return -ENODEV; } -static int __devinit au1550nd_probe(struct platform_device *pdev) +static int au1550nd_probe(struct platform_device *pdev) { struct au1550nd_platdata *pd; struct au1550nd_ctx *ctx; @@ -491,7 +491,7 @@ out1: return ret; } -static int __devexit au1550nd_remove(struct platform_device *pdev) +static int au1550nd_remove(struct platform_device *pdev) { struct au1550nd_ctx *ctx = platform_get_drvdata(pdev); struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -509,7 +509,7 @@ static struct platform_driver au1550nd_driver = { .owner = THIS_MODULE, }, .probe = au1550nd_probe, - .remove = __devexit_p(au1550nd_remove), + .remove = au1550nd_remove, }; module_platform_driver(au1550nd_driver); diff --git a/drivers/mtd/nand/autcpu12.c b/drivers/mtd/nand/autcpu12.c deleted file mode 100644 index 04769a49a7cb..000000000000 --- a/drivers/mtd/nand/autcpu12.c +++ /dev/null @@ -1,237 +0,0 @@ -/* - * drivers/mtd/autcpu12.c - * - * Copyright (c) 2002 Thomas Gleixner <tgxl@linutronix.de> - * - * Derived from drivers/mtd/spia.c - * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Overview: - * This is a device driver for the NAND flash device found on the - * autronix autcpu12 board, which is a SmartMediaCard. It supports - * 16MiB, 32MiB and 64MiB cards. - * - * - * 02-12-2002 TG Cleanup of module params - * - * 02-20-2002 TG adjusted for different rd/wr address support - * added support for read device ready/busy line - * added page_cache - * - * 10-06-2002 TG 128K card support added - */ - -#include <linux/slab.h> -#include <linux/init.h> -#include <linux/module.h> -#include <linux/mtd/mtd.h> -#include <linux/mtd/nand.h> -#include <linux/mtd/partitions.h> -#include <asm/io.h> -#include <mach/hardware.h> -#include <asm/sizes.h> -#include <mach/autcpu12.h> - -/* - * MTD structure for AUTCPU12 board - */ -static struct mtd_info *autcpu12_mtd = NULL; -static void __iomem *autcpu12_fio_base; - -/* - * Define partitions for flash devices - */ -static struct mtd_partition partition_info16k[] = { - { .name = "AUTCPU12 flash partition 1", - .offset = 0, - .size = 8 * SZ_1M }, - { .name = "AUTCPU12 flash partition 2", - .offset = 8 * SZ_1M, - .size = 8 * SZ_1M }, -}; - -static struct mtd_partition partition_info32k[] = { - { .name = "AUTCPU12 flash partition 1", - .offset = 0, - .size = 8 * SZ_1M }, - { .name = "AUTCPU12 flash partition 2", - .offset = 8 * SZ_1M, - .size = 24 * SZ_1M }, -}; - -static struct mtd_partition partition_info64k[] = { - { .name = "AUTCPU12 flash partition 1", - .offset = 0, - .size = 16 * SZ_1M }, - { .name = "AUTCPU12 flash partition 2", - .offset = 16 * SZ_1M, - .size = 48 * SZ_1M }, -}; - -static struct mtd_partition partition_info128k[] = { - { .name = "AUTCPU12 flash partition 1", - .offset = 0, - .size = 16 * SZ_1M }, - { .name = "AUTCPU12 flash partition 2", - .offset = 16 * SZ_1M, - .size = 112 * SZ_1M }, -}; - -#define NUM_PARTITIONS16K 2 -#define NUM_PARTITIONS32K 2 -#define NUM_PARTITIONS64K 2 -#define NUM_PARTITIONS128K 2 -/* - * hardware specific access to control-lines - * - * ALE bit 4 autcpu12_pedr - * CLE bit 5 autcpu12_pedr - * NCE bit 0 fio_ctrl - * - */ -static void autcpu12_hwcontrol(struct mtd_info *mtd, int cmd, - unsigned int ctrl) -{ - struct nand_chip *chip = mtd->priv; - - if (ctrl & NAND_CTRL_CHANGE) { - void __iomem *addr; - unsigned char bits; - - bits = clps_readb(AUTCPU12_SMC_PORT_OFFSET) & ~0x30; - bits |= (ctrl & NAND_CLE) << 4; - bits |= (ctrl & NAND_ALE) << 2; - clps_writeb(bits, AUTCPU12_SMC_PORT_OFFSET); - - addr = autcpu12_fio_base + AUTCPU12_SMC_SELECT_OFFSET; - writeb((readb(addr) & ~0x1) | (ctrl & NAND_NCE), addr); - } - - if (cmd != NAND_CMD_NONE) - writeb(cmd, chip->IO_ADDR_W); -} - -/* - * read device ready pin - */ -int autcpu12_device_ready(struct mtd_info *mtd) -{ - return clps_readb(AUTCPU12_SMC_PORT_OFFSET) & AUTCPU12_SMC_RDY; -} - -/* - * Main initialization routine - */ -static int __init autcpu12_init(void) -{ - struct nand_chip *this; - int err = 0; - - /* Allocate memory for MTD device structure and private data */ - autcpu12_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), - GFP_KERNEL); - if (!autcpu12_mtd) { - printk("Unable to allocate AUTCPU12 NAND MTD device structure.\n"); - err = -ENOMEM; - goto out; - } - - /* map physical address */ - autcpu12_fio_base = ioremap(AUTCPU12_PHYS_SMC, SZ_1K); - if (!autcpu12_fio_base) { - printk("Ioremap autcpu12 SmartMedia Card failed\n"); - err = -EIO; - goto out_mtd; - } - - /* Get pointer to private data */ - this = (struct nand_chip *)(&autcpu12_mtd[1]); - - /* Initialize structures */ - memset(autcpu12_mtd, 0, sizeof(struct mtd_info)); - memset(this, 0, sizeof(struct nand_chip)); - - /* Link the private data with the MTD structure */ - autcpu12_mtd->priv = this; - autcpu12_mtd->owner = THIS_MODULE; - - /* Set address of NAND IO lines */ - this->IO_ADDR_R = autcpu12_fio_base; - this->IO_ADDR_W = autcpu12_fio_base; - this->cmd_ctrl = autcpu12_hwcontrol; - this->dev_ready = autcpu12_device_ready; - /* 20 us command delay time */ - this->chip_delay = 20; - this->ecc.mode = NAND_ECC_SOFT; - - /* Enable the following for a flash based bad block table */ - /* - this->bbt_options = NAND_BBT_USE_FLASH; - */ - this->bbt_options = NAND_BBT_USE_FLASH; - - /* Scan to find existence of the device */ - if (nand_scan(autcpu12_mtd, 1)) { - err = -ENXIO; - goto out_ior; - } - - /* Register the partitions */ - switch (autcpu12_mtd->size) { - case SZ_16M: - mtd_device_register(autcpu12_mtd, partition_info16k, - NUM_PARTITIONS16K); - break; - case SZ_32M: - mtd_device_register(autcpu12_mtd, partition_info32k, - NUM_PARTITIONS32K); - break; - case SZ_64M: - mtd_device_register(autcpu12_mtd, partition_info64k, - NUM_PARTITIONS64K); - break; - case SZ_128M: - mtd_device_register(autcpu12_mtd, partition_info128k, - NUM_PARTITIONS128K); - break; - default: - printk("Unsupported SmartMedia device\n"); - err = -ENXIO; - goto out_ior; - } - goto out; - - out_ior: - iounmap(autcpu12_fio_base); - out_mtd: - kfree(autcpu12_mtd); - out: - return err; -} - -module_init(autcpu12_init); - -/* - * Clean up routine - */ -static void __exit autcpu12_cleanup(void) -{ - /* Release resources, unregister device */ - nand_release(autcpu12_mtd); - - /* unmap physical address */ - iounmap(autcpu12_fio_base); - - /* Free the MTD device structure */ - kfree(autcpu12_mtd); -} - -module_exit(autcpu12_cleanup); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Thomas Gleixner <tglx@linutronix.de>"); -MODULE_DESCRIPTION("Glue layer for SmartMediaCard on autronix autcpu12"); diff --git a/drivers/mtd/nand/bcm47xxnflash/Makefile b/drivers/mtd/nand/bcm47xxnflash/Makefile new file mode 100644 index 000000000000..f05b119e134b --- /dev/null +++ b/drivers/mtd/nand/bcm47xxnflash/Makefile @@ -0,0 +1,4 @@ +bcm47xxnflash-y += main.o +bcm47xxnflash-y += ops_bcm4706.o + +obj-$(CONFIG_MTD_NAND_BCM47XXNFLASH) += bcm47xxnflash.o diff --git a/drivers/mtd/nand/bcm47xxnflash/bcm47xxnflash.h b/drivers/mtd/nand/bcm47xxnflash/bcm47xxnflash.h new file mode 100644 index 000000000000..0bdb2ce4da75 --- /dev/null +++ b/drivers/mtd/nand/bcm47xxnflash/bcm47xxnflash.h @@ -0,0 +1,22 @@ +#ifndef __BCM47XXNFLASH_H +#define __BCM47XXNFLASH_H + +#include <linux/mtd/mtd.h> +#include <linux/mtd/nand.h> + +struct bcm47xxnflash { + struct bcma_drv_cc *cc; + + struct nand_chip nand_chip; + struct mtd_info mtd; + + unsigned curr_command; + int curr_page_addr; + int curr_column; + + u8 id_data[8]; +}; + +int bcm47xxnflash_ops_bcm4706_init(struct bcm47xxnflash *b47n); + +#endif /* BCM47XXNFLASH */ diff --git a/drivers/mtd/nand/bcm47xxnflash/main.c b/drivers/mtd/nand/bcm47xxnflash/main.c new file mode 100644 index 000000000000..2b8b05bec3dd --- /dev/null +++ b/drivers/mtd/nand/bcm47xxnflash/main.c @@ -0,0 +1,108 @@ +/* + * BCM47XX NAND flash driver + * + * Copyright (C) 2012 Rafał Miłecki <zajec5@gmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/platform_device.h> +#include <linux/bcma/bcma.h> + +#include "bcm47xxnflash.h" + +MODULE_DESCRIPTION("NAND flash driver for BCMA bus"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Rafał Miłecki"); + +static const char *probes[] = { "bcm47xxpart", NULL }; + +static int bcm47xxnflash_probe(struct platform_device *pdev) +{ + struct bcma_nflash *nflash = dev_get_platdata(&pdev->dev); + struct bcm47xxnflash *b47n; + int err = 0; + + b47n = kzalloc(sizeof(*b47n), GFP_KERNEL); + if (!b47n) { + err = -ENOMEM; + goto out; + } + + b47n->nand_chip.priv = b47n; + b47n->mtd.owner = THIS_MODULE; + b47n->mtd.priv = &b47n->nand_chip; /* Required */ + b47n->cc = container_of(nflash, struct bcma_drv_cc, nflash); + + if (b47n->cc->core->bus->chipinfo.id == BCMA_CHIP_ID_BCM4706) { + err = bcm47xxnflash_ops_bcm4706_init(b47n); + } else { + pr_err("Device not supported\n"); + err = -ENOTSUPP; + } + if (err) { + pr_err("Initialization failed: %d\n", err); + goto err_init; + } + + err = mtd_device_parse_register(&b47n->mtd, probes, NULL, NULL, 0); + if (err) { + pr_err("Failed to register MTD device: %d\n", err); + goto err_dev_reg; + } + + return 0; + +err_dev_reg: +err_init: + kfree(b47n); +out: + return err; +} + +static int __devexit bcm47xxnflash_remove(struct platform_device *pdev) +{ + struct bcma_nflash *nflash = dev_get_platdata(&pdev->dev); + + if (nflash->mtd) + mtd_device_unregister(nflash->mtd); + + return 0; +} + +static struct platform_driver bcm47xxnflash_driver = { + .remove = __devexit_p(bcm47xxnflash_remove), + .driver = { + .name = "bcma_nflash", + .owner = THIS_MODULE, + }, +}; + +static int __init bcm47xxnflash_init(void) +{ + int err; + + /* + * Platform device "bcma_nflash" exists on SoCs and is registered very + * early, it won't be added during runtime (use platform_driver_probe). + */ + err = platform_driver_probe(&bcm47xxnflash_driver, bcm47xxnflash_probe); + if (err) + pr_err("Failed to register serial flash driver: %d\n", err); + + return err; +} + +static void __exit bcm47xxnflash_exit(void) +{ + platform_driver_unregister(&bcm47xxnflash_driver); +} + +module_init(bcm47xxnflash_init); +module_exit(bcm47xxnflash_exit); diff --git a/drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c b/drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c new file mode 100644 index 000000000000..86c9a79b89b3 --- /dev/null +++ b/drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c @@ -0,0 +1,413 @@ +/* + * BCM47XX NAND flash driver + * + * Copyright (C) 2012 Rafał Miłecki <zajec5@gmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/bcma/bcma.h> + +#include "bcm47xxnflash.h" + +/* Broadcom uses 1'000'000 but it seems to be too many. Tests on WNDR4500 has + * shown 164 retries as maxiumum. */ +#define NFLASH_READY_RETRIES 1000 + +#define NFLASH_SECTOR_SIZE 512 + +#define NCTL_CMD0 0x00010000 +#define NCTL_CMD1W 0x00080000 +#define NCTL_READ 0x00100000 +#define NCTL_WRITE 0x00200000 +#define NCTL_SPECADDR 0x01000000 +#define NCTL_READY 0x04000000 +#define NCTL_ERR 0x08000000 +#define NCTL_CSA 0x40000000 +#define NCTL_START 0x80000000 + +/************************************************** + * Various helpers + **************************************************/ + +static inline u8 bcm47xxnflash_ops_bcm4706_ns_to_cycle(u16 ns, u16 clock) +{ + return ((ns * 1000 * clock) / 1000000) + 1; +} + +static int bcm47xxnflash_ops_bcm4706_ctl_cmd(struct bcma_drv_cc *cc, u32 code) +{ + int i = 0; + + bcma_cc_write32(cc, BCMA_CC_NFLASH_CTL, NCTL_START | code); + for (i = 0; i < NFLASH_READY_RETRIES; i++) { + if (!(bcma_cc_read32(cc, BCMA_CC_NFLASH_CTL) & NCTL_START)) { + i = 0; + break; + } + } + if (i) { + pr_err("NFLASH control command not ready!\n"); + return -EBUSY; + } + return 0; +} + +static int bcm47xxnflash_ops_bcm4706_poll(struct bcma_drv_cc *cc) +{ + int i; + + for (i = 0; i < NFLASH_READY_RETRIES; i++) { + if (bcma_cc_read32(cc, BCMA_CC_NFLASH_CTL) & NCTL_READY) { + if (bcma_cc_read32(cc, BCMA_CC_NFLASH_CTL) & + BCMA_CC_NFLASH_CTL_ERR) { + pr_err("Error on polling\n"); + return -EBUSY; + } else { + return 0; + } + } + } + + pr_err("Polling timeout!\n"); + return -EBUSY; +} + +/************************************************** + * R/W + **************************************************/ + +static void bcm47xxnflash_ops_bcm4706_read(struct mtd_info *mtd, uint8_t *buf, + int len) +{ + struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv; + struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv; + + u32 ctlcode; + u32 *dest = (u32 *)buf; + int i; + int toread; + + BUG_ON(b47n->curr_page_addr & ~nand_chip->pagemask); + /* Don't validate column using nand_chip->page_shift, it may be bigger + * when accessing OOB */ + + while (len) { + /* We can read maximum of 0x200 bytes at once */ + toread = min(len, 0x200); + + /* Set page and column */ + bcma_cc_write32(b47n->cc, BCMA_CC_NFLASH_COL_ADDR, + b47n->curr_column); + bcma_cc_write32(b47n->cc, BCMA_CC_NFLASH_ROW_ADDR, + b47n->curr_page_addr); + + /* Prepare to read */ + ctlcode = NCTL_CSA | NCTL_CMD1W | 0x00040000 | 0x00020000 | + NCTL_CMD0; + ctlcode |= NAND_CMD_READSTART << 8; + if (bcm47xxnflash_ops_bcm4706_ctl_cmd(b47n->cc, ctlcode)) + return; + if (bcm47xxnflash_ops_bcm4706_poll(b47n->cc)) + return; + + /* Eventually read some data :) */ + for (i = 0; i < toread; i += 4, dest++) { + ctlcode = NCTL_CSA | 0x30000000 | NCTL_READ; + if (i == toread - 4) /* Last read goes without that */ + ctlcode &= ~NCTL_CSA; + if (bcm47xxnflash_ops_bcm4706_ctl_cmd(b47n->cc, + ctlcode)) + return; + *dest = bcma_cc_read32(b47n->cc, BCMA_CC_NFLASH_DATA); + } + + b47n->curr_column += toread; + len -= toread; + } +} + +static void bcm47xxnflash_ops_bcm4706_write(struct mtd_info *mtd, + const uint8_t *buf, int len) +{ + struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv; + struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv; + struct bcma_drv_cc *cc = b47n->cc; + + u32 ctlcode; + const u32 *data = (u32 *)buf; + int i; + + BUG_ON(b47n->curr_page_addr & ~nand_chip->pagemask); + /* Don't validate column using nand_chip->page_shift, it may be bigger + * when accessing OOB */ + + for (i = 0; i < len; i += 4, data++) { + bcma_cc_write32(cc, BCMA_CC_NFLASH_DATA, *data); + + ctlcode = NCTL_CSA | 0x30000000 | NCTL_WRITE; + if (i == len - 4) /* Last read goes without that */ + ctlcode &= ~NCTL_CSA; + if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, ctlcode)) { + pr_err("%s ctl_cmd didn't work!\n", __func__); + return; + } + } + + b47n->curr_column += len; +} + +/************************************************** + * NAND chip ops + **************************************************/ + +/* Default nand_select_chip calls cmd_ctrl, which is not used in BCM4706 */ +static void bcm47xxnflash_ops_bcm4706_select_chip(struct mtd_info *mtd, + int chip) +{ + return; +} + +/* + * Default nand_command and nand_command_lp don't match BCM4706 hardware layout. + * For example, reading chip id is performed in a non-standard way. + * Setting column and page is also handled differently, we use a special + * registers of ChipCommon core. Hacking cmd_ctrl to understand and convert + * standard commands would be much more complicated. + */ +static void bcm47xxnflash_ops_bcm4706_cmdfunc(struct mtd_info *mtd, + unsigned command, int column, + int page_addr) +{ + struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv; + struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv; + struct bcma_drv_cc *cc = b47n->cc; + u32 ctlcode; + int i; + + if (column != -1) + b47n->curr_column = column; + if (page_addr != -1) + b47n->curr_page_addr = page_addr; + + switch (command) { + case NAND_CMD_RESET: + pr_warn("Chip reset not implemented yet\n"); + break; + case NAND_CMD_READID: + ctlcode = NCTL_CSA | 0x01000000 | NCTL_CMD1W | NCTL_CMD0; + ctlcode |= NAND_CMD_READID; + if (bcm47xxnflash_ops_bcm4706_ctl_cmd(b47n->cc, ctlcode)) { + pr_err("READID error\n"); + break; + } + + /* + * Reading is specific, last one has to go without NCTL_CSA + * bit. We don't know how many reads NAND subsystem is going + * to perform, so cache everything. + */ + for (i = 0; i < ARRAY_SIZE(b47n->id_data); i++) { + ctlcode = NCTL_CSA | NCTL_READ; + if (i == ARRAY_SIZE(b47n->id_data) - 1) + ctlcode &= ~NCTL_CSA; + if (bcm47xxnflash_ops_bcm4706_ctl_cmd(b47n->cc, + ctlcode)) { + pr_err("READID error\n"); + break; + } + b47n->id_data[i] = + bcma_cc_read32(b47n->cc, BCMA_CC_NFLASH_DATA) + & 0xFF; + } + + break; + case NAND_CMD_STATUS: + ctlcode = NCTL_CSA | NCTL_CMD0 | NAND_CMD_STATUS; + if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, ctlcode)) + pr_err("STATUS command error\n"); + break; + case NAND_CMD_READ0: + break; + case NAND_CMD_READOOB: + if (page_addr != -1) + b47n->curr_column += mtd->writesize; + break; + case NAND_CMD_ERASE1: + bcma_cc_write32(cc, BCMA_CC_NFLASH_ROW_ADDR, + b47n->curr_page_addr); + ctlcode = 0x00040000 | NCTL_CMD1W | NCTL_CMD0 | + NAND_CMD_ERASE1 | (NAND_CMD_ERASE2 << 8); + if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, ctlcode)) + pr_err("ERASE1 failed\n"); + break; + case NAND_CMD_ERASE2: + break; + case NAND_CMD_SEQIN: + /* Set page and column */ + bcma_cc_write32(cc, BCMA_CC_NFLASH_COL_ADDR, + b47n->curr_column); + bcma_cc_write32(cc, BCMA_CC_NFLASH_ROW_ADDR, + b47n->curr_page_addr); + + /* Prepare to write */ + ctlcode = 0x40000000 | 0x00040000 | 0x00020000 | 0x00010000; + ctlcode |= NAND_CMD_SEQIN; + if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, ctlcode)) + pr_err("SEQIN failed\n"); + break; + case NAND_CMD_PAGEPROG: + if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, 0x00010000 | + NAND_CMD_PAGEPROG)) + pr_err("PAGEPROG failed\n"); + if (bcm47xxnflash_ops_bcm4706_poll(cc)) + pr_err("PAGEPROG not ready\n"); + break; + default: + pr_err("Command 0x%X unsupported\n", command); + break; + } + b47n->curr_command = command; +} + +static u8 bcm47xxnflash_ops_bcm4706_read_byte(struct mtd_info *mtd) +{ + struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv; + struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv; + struct bcma_drv_cc *cc = b47n->cc; + u32 tmp = 0; + + switch (b47n->curr_command) { + case NAND_CMD_READID: + if (b47n->curr_column >= ARRAY_SIZE(b47n->id_data)) { + pr_err("Requested invalid id_data: %d\n", + b47n->curr_column); + return 0; + } + return b47n->id_data[b47n->curr_column++]; + case NAND_CMD_STATUS: + if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, NCTL_READ)) + return 0; + return bcma_cc_read32(cc, BCMA_CC_NFLASH_DATA) & 0xff; + case NAND_CMD_READOOB: + bcm47xxnflash_ops_bcm4706_read(mtd, (u8 *)&tmp, 4); + return tmp & 0xFF; + } + + pr_err("Invalid command for byte read: 0x%X\n", b47n->curr_command); + return 0; +} + +static void bcm47xxnflash_ops_bcm4706_read_buf(struct mtd_info *mtd, + uint8_t *buf, int len) +{ + struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv; + struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv; + + switch (b47n->curr_command) { + case NAND_CMD_READ0: + case NAND_CMD_READOOB: + bcm47xxnflash_ops_bcm4706_read(mtd, buf, len); + return; + } + + pr_err("Invalid command for buf read: 0x%X\n", b47n->curr_command); +} + +static void bcm47xxnflash_ops_bcm4706_write_buf(struct mtd_info *mtd, + const uint8_t *buf, int len) +{ + struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv; + struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv; + + switch (b47n->curr_command) { + case NAND_CMD_SEQIN: + bcm47xxnflash_ops_bcm4706_write(mtd, buf, len); + return; + } + + pr_err("Invalid command for buf write: 0x%X\n", b47n->curr_command); +} + +/************************************************** + * Init + **************************************************/ + +int bcm47xxnflash_ops_bcm4706_init(struct bcm47xxnflash *b47n) +{ + int err; + u32 freq; + u16 clock; + u8 w0, w1, w2, w3, w4; + + unsigned long chipsize; /* MiB */ + u8 tbits, col_bits, col_size, row_bits, row_bsize; + u32 val; + + b47n->nand_chip.select_chip = bcm47xxnflash_ops_bcm4706_select_chip; + b47n->nand_chip.cmdfunc = bcm47xxnflash_ops_bcm4706_cmdfunc; + b47n->nand_chip.read_byte = bcm47xxnflash_ops_bcm4706_read_byte; + b47n->nand_chip.read_buf = bcm47xxnflash_ops_bcm4706_read_buf; + b47n->nand_chip.write_buf = bcm47xxnflash_ops_bcm4706_write_buf; + b47n->nand_chip.bbt_options = NAND_BBT_USE_FLASH; + b47n->nand_chip.ecc.mode = NAND_ECC_NONE; /* TODO: implement ECC */ + + /* Enable NAND flash access */ + bcma_cc_set32(b47n->cc, BCMA_CC_4706_FLASHSCFG, + BCMA_CC_4706_FLASHSCFG_NF1); + + /* Configure wait counters */ + if (b47n->cc->status & BCMA_CC_CHIPST_4706_PKG_OPTION) { + freq = 100000000; + } else { + freq = bcma_chipco_pll_read(b47n->cc, 4); + freq = (freq * 0xFFF) >> 3; + freq = (freq * 25000000) >> 3; + } + clock = freq / 1000000; + w0 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(15, clock); + w1 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(20, clock); + w2 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(10, clock); + w3 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(10, clock); + w4 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(100, clock); + bcma_cc_write32(b47n->cc, BCMA_CC_NFLASH_WAITCNT0, + (w4 << 24 | w3 << 18 | w2 << 12 | w1 << 6 | w0)); + + /* Scan NAND */ + err = nand_scan(&b47n->mtd, 1); + if (err) { + pr_err("Could not scan NAND flash: %d\n", err); + goto exit; + } + + /* Configure FLASH */ + chipsize = b47n->nand_chip.chipsize >> 20; + tbits = ffs(chipsize); /* find first bit set */ + if (!tbits || tbits != fls(chipsize)) { + pr_err("Invalid flash size: 0x%lX\n", chipsize); + err = -ENOTSUPP; + goto exit; + } + tbits += 19; /* Broadcom increases *index* by 20, we increase *pos* */ + + col_bits = b47n->nand_chip.page_shift + 1; + col_size = (col_bits + 7) / 8; + + row_bits = tbits - col_bits + 1; + row_bsize = (row_bits + 7) / 8; + + val = ((row_bsize - 1) << 6) | ((col_size - 1) << 4) | 2; + bcma_cc_write32(b47n->cc, BCMA_CC_NFLASH_CONF, val); + +exit: + if (err) + bcma_cc_mask32(b47n->cc, BCMA_CC_4706_FLASHSCFG, + ~BCMA_CC_4706_FLASHSCFG_NF1); + return err; +} diff --git a/drivers/mtd/nand/bf5xx_nand.c b/drivers/mtd/nand/bf5xx_nand.c index ab0caa74eb43..4271e948d1e2 100644 --- a/drivers/mtd/nand/bf5xx_nand.c +++ b/drivers/mtd/nand/bf5xx_nand.c @@ -658,7 +658,7 @@ static int bf5xx_nand_hw_init(struct bf5xx_nand_info *info) /* * Device management interface */ -static int __devinit bf5xx_nand_add_partition(struct bf5xx_nand_info *info) +static int bf5xx_nand_add_partition(struct bf5xx_nand_info *info) { struct mtd_info *mtd = &info->mtd; struct mtd_partition *parts = info->platform->partitions; @@ -667,7 +667,7 @@ static int __devinit bf5xx_nand_add_partition(struct bf5xx_nand_info *info) return mtd_device_register(mtd, parts, nr); } -static int __devexit bf5xx_nand_remove(struct platform_device *pdev) +static int bf5xx_nand_remove(struct platform_device *pdev) { struct bf5xx_nand_info *info = to_nand_info(pdev); @@ -725,7 +725,7 @@ static int bf5xx_nand_scan(struct mtd_info *mtd) * it can allocate all necessary resources then calls the * nand layer to look for devices */ -static int __devinit bf5xx_nand_probe(struct platform_device *pdev) +static int bf5xx_nand_probe(struct platform_device *pdev) { struct bf5xx_nand_platform *plat = to_nand_plat(pdev); struct bf5xx_nand_info *info = NULL; @@ -865,7 +865,7 @@ static int bf5xx_nand_resume(struct platform_device *dev) /* driver device registration */ static struct platform_driver bf5xx_nand_driver = { .probe = bf5xx_nand_probe, - .remove = __devexit_p(bf5xx_nand_remove), + .remove = bf5xx_nand_remove, .suspend = bf5xx_nand_suspend, .resume = bf5xx_nand_resume, .driver = { diff --git a/drivers/mtd/nand/cafe_nand.c b/drivers/mtd/nand/cafe_nand.c index 2bb7170502c2..010d61266536 100644 --- a/drivers/mtd/nand/cafe_nand.c +++ b/drivers/mtd/nand/cafe_nand.c @@ -585,7 +585,7 @@ static int cafe_nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) } /* F_2[X]/(X**6+X+1) */ -static unsigned short __devinit gf64_mul(u8 a, u8 b) +static unsigned short gf64_mul(u8 a, u8 b) { u8 c; unsigned int i; @@ -604,7 +604,7 @@ static unsigned short __devinit gf64_mul(u8 a, u8 b) } /* F_64[X]/(X**2+X+A**-1) with A the generator of F_64[X] */ -static u16 __devinit gf4096_mul(u16 a, u16 b) +static u16 gf4096_mul(u16 a, u16 b) { u8 ah, al, bh, bl, ch, cl; @@ -619,14 +619,14 @@ static u16 __devinit gf4096_mul(u16 a, u16 b) return (ch << 6) ^ cl; } -static int __devinit cafe_mul(int x) +static int cafe_mul(int x) { if (x == 0) return 1; return gf4096_mul(x, 0xe01); } -static int __devinit cafe_nand_probe(struct pci_dev *pdev, +static int cafe_nand_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct mtd_info *mtd; @@ -821,7 +821,7 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev, return err; } -static void __devexit cafe_nand_remove(struct pci_dev *pdev) +static void cafe_nand_remove(struct pci_dev *pdev) { struct mtd_info *mtd = pci_get_drvdata(pdev); struct cafe_priv *cafe = mtd->priv; @@ -887,7 +887,7 @@ static struct pci_driver cafe_nand_pci_driver = { .name = "CAFÉ NAND", .id_table = cafe_nand_tbl, .probe = cafe_nand_probe, - .remove = __devexit_p(cafe_nand_remove), + .remove = cafe_nand_remove, .resume = cafe_nand_resume, }; diff --git a/drivers/mtd/nand/cs553x_nand.c b/drivers/mtd/nand/cs553x_nand.c index adb6c3ef37fb..2cdeab8bebc4 100644 --- a/drivers/mtd/nand/cs553x_nand.c +++ b/drivers/mtd/nand/cs553x_nand.c @@ -237,6 +237,7 @@ static int __init cs553x_init_one(int cs, int mmio, unsigned long adr) this->ecc.hwctl = cs_enable_hwecc; this->ecc.calculate = cs_calculate_ecc; this->ecc.correct = nand_correct_data; + this->ecc.strength = 1; /* Enable the following for a flash based bad block table */ this->bbt_options = NAND_BBT_USE_FLASH; @@ -247,8 +248,6 @@ static int __init cs553x_init_one(int cs, int mmio, unsigned long adr) goto out_ior; } - this->ecc.strength = 1; - new_mtd->name = kasprintf(GFP_KERNEL, "cs553x_nand_cs%d", cs); cs553x_mtd[cs] = new_mtd; diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c index 945047ad0952..3502606f6480 100644 --- a/drivers/mtd/nand/davinci_nand.c +++ b/drivers/mtd/nand/davinci_nand.c @@ -821,9 +821,16 @@ syndrome_done: if (ret < 0) goto err_scan; - ret = mtd_device_parse_register(&info->mtd, NULL, NULL, pdata->parts, - pdata->nr_parts); - + if (pdata->parts) + ret = mtd_device_parse_register(&info->mtd, NULL, NULL, + pdata->parts, pdata->nr_parts); + else { + struct mtd_part_parser_data ppdata; + + ppdata.of_node = pdev->dev.of_node; + ret = mtd_device_parse_register(&info->mtd, NULL, &ppdata, + NULL, 0); + } if (ret < 0) goto err_scan; diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c index e706a237170f..0c8bb6bf8424 100644 --- a/drivers/mtd/nand/denali.c +++ b/drivers/mtd/nand/denali.c @@ -16,14 +16,12 @@ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * */ - #include <linux/interrupt.h> #include <linux/delay.h> #include <linux/dma-mapping.h> #include <linux/wait.h> #include <linux/mutex.h> #include <linux/slab.h> -#include <linux/pci.h> #include <linux/mtd/mtd.h> #include <linux/module.h> @@ -89,13 +87,6 @@ MODULE_PARM_DESC(onfi_timing_mode, "Overrides default ONFI setting." * format the bank into the proper bits for the controller */ #define BANK(x) ((x) << 24) -/* List of platforms this NAND controller has be integrated into */ -static const struct pci_device_id denali_pci_ids[] = { - { PCI_VDEVICE(INTEL, 0x0701), INTEL_CE4100 }, - { PCI_VDEVICE(INTEL, 0x0809), INTEL_MRST }, - { /* end: all zeroes */ } -}; - /* forward declarations */ static void clear_interrupts(struct denali_nand_info *denali); static uint32_t wait_for_irq(struct denali_nand_info *denali, @@ -699,7 +690,7 @@ static uint32_t wait_for_irq(struct denali_nand_info *denali, uint32_t irq_mask) if (comp_res == 0) { /* timeout */ - printk(KERN_ERR "timeout occurred, status = 0x%x, mask = 0x%x\n", + pr_err("timeout occurred, status = 0x%x, mask = 0x%x\n", intr_status, irq_mask); intr_status = 0; @@ -1305,8 +1296,7 @@ static void denali_cmdfunc(struct mtd_info *mtd, unsigned int cmd, int col, /* TODO: Read OOB data */ break; default: - printk(KERN_ERR ": unsupported command" - " received 0x%x\n", cmd); + pr_err(": unsupported command received 0x%x\n", cmd); break; } } @@ -1425,107 +1415,48 @@ void denali_drv_init(struct denali_nand_info *denali) denali->irq_status = 0; } -/* driver entry point */ -static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) +int denali_init(struct denali_nand_info *denali) { - int ret = -ENODEV; - resource_size_t csr_base, mem_base; - unsigned long csr_len, mem_len; - struct denali_nand_info *denali; - - denali = kzalloc(sizeof(*denali), GFP_KERNEL); - if (!denali) - return -ENOMEM; + int ret; - ret = pci_enable_device(dev); - if (ret) { - printk(KERN_ERR "Spectra: pci_enable_device failed.\n"); - goto failed_alloc_memery; - } - - if (id->driver_data == INTEL_CE4100) { + if (denali->platform == INTEL_CE4100) { /* Due to a silicon limitation, we can only support * ONFI timing mode 1 and below. */ if (onfi_timing_mode < -1 || onfi_timing_mode > 1) { - printk(KERN_ERR "Intel CE4100 only supports" - " ONFI timing mode 1 or below\n"); - ret = -EINVAL; - goto failed_enable_dev; - } - denali->platform = INTEL_CE4100; - mem_base = pci_resource_start(dev, 0); - mem_len = pci_resource_len(dev, 1); - csr_base = pci_resource_start(dev, 1); - csr_len = pci_resource_len(dev, 1); - } else { - denali->platform = INTEL_MRST; - csr_base = pci_resource_start(dev, 0); - csr_len = pci_resource_len(dev, 0); - mem_base = pci_resource_start(dev, 1); - mem_len = pci_resource_len(dev, 1); - if (!mem_len) { - mem_base = csr_base + csr_len; - mem_len = csr_len; + pr_err("Intel CE4100 only supports ONFI timing mode 1 or below\n"); + return -EINVAL; } } /* Is 32-bit DMA supported? */ - ret = dma_set_mask(&dev->dev, DMA_BIT_MASK(32)); + ret = dma_set_mask(denali->dev, DMA_BIT_MASK(32)); if (ret) { - printk(KERN_ERR "Spectra: no usable DMA configuration\n"); - goto failed_enable_dev; + pr_err("Spectra: no usable DMA configuration\n"); + return ret; } - denali->buf.dma_buf = dma_map_single(&dev->dev, denali->buf.buf, + denali->buf.dma_buf = dma_map_single(denali->dev, denali->buf.buf, DENALI_BUF_SIZE, DMA_BIDIRECTIONAL); - if (dma_mapping_error(&dev->dev, denali->buf.dma_buf)) { - dev_err(&dev->dev, "Spectra: failed to map DMA buffer\n"); - goto failed_enable_dev; - } - - pci_set_master(dev); - denali->dev = &dev->dev; - denali->mtd.dev.parent = &dev->dev; - - ret = pci_request_regions(dev, DENALI_NAND_NAME); - if (ret) { - printk(KERN_ERR "Spectra: Unable to request memory regions\n"); - goto failed_dma_map; - } - - denali->flash_reg = ioremap_nocache(csr_base, csr_len); - if (!denali->flash_reg) { - printk(KERN_ERR "Spectra: Unable to remap memory region\n"); - ret = -ENOMEM; - goto failed_req_regions; - } - - denali->flash_mem = ioremap_nocache(mem_base, mem_len); - if (!denali->flash_mem) { - printk(KERN_ERR "Spectra: ioremap_nocache failed!"); - ret = -ENOMEM; - goto failed_remap_reg; + if (dma_mapping_error(denali->dev, denali->buf.dma_buf)) { + dev_err(denali->dev, "Spectra: failed to map DMA buffer\n"); + return -EIO; } - + denali->mtd.dev.parent = denali->dev; denali_hw_init(denali); denali_drv_init(denali); /* denali_isr register is done after all the hardware * initilization is finished*/ - if (request_irq(dev->irq, denali_isr, IRQF_SHARED, + if (request_irq(denali->irq, denali_isr, IRQF_SHARED, DENALI_NAND_NAME, denali)) { - printk(KERN_ERR "Spectra: Unable to allocate IRQ\n"); - ret = -ENODEV; - goto failed_remap_mem; + pr_err("Spectra: Unable to allocate IRQ\n"); + return -ENODEV; } /* now that our ISR is registered, we can enable interrupts */ denali_set_intr_modes(denali, true); - - pci_set_drvdata(dev, denali); - denali->mtd.name = "denali-nand"; denali->mtd.owner = THIS_MODULE; denali->mtd.priv = &denali->nand; @@ -1549,8 +1480,7 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) */ if (denali->mtd.writesize > NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE) { ret = -ENODEV; - printk(KERN_ERR "Spectra: device size not supported by this " - "version of MTD."); + pr_err("Spectra: device size not supported by this version of MTD."); goto failed_req_irq; } @@ -1602,8 +1532,8 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) } else if (denali->mtd.oobsize < (denali->bbtskipbytes + ECC_8BITS * (denali->mtd.writesize / ECC_SECTOR_SIZE))) { - printk(KERN_ERR "Your NAND chip OOB is not large enough to" - " contain 8bit ECC correction codes"); + pr_err("Your NAND chip OOB is not large enough to \ + contain 8bit ECC correction codes"); goto failed_req_irq; } else { denali->nand.ecc.strength = 8; @@ -1655,56 +1585,24 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) ret = mtd_device_register(&denali->mtd, NULL, 0); if (ret) { - dev_err(&dev->dev, "Spectra: Failed to register MTD: %d\n", + dev_err(denali->dev, "Spectra: Failed to register MTD: %d\n", ret); goto failed_req_irq; } return 0; failed_req_irq: - denali_irq_cleanup(dev->irq, denali); -failed_remap_mem: - iounmap(denali->flash_mem); -failed_remap_reg: - iounmap(denali->flash_reg); -failed_req_regions: - pci_release_regions(dev); -failed_dma_map: - dma_unmap_single(&dev->dev, denali->buf.dma_buf, DENALI_BUF_SIZE, - DMA_BIDIRECTIONAL); -failed_enable_dev: - pci_disable_device(dev); -failed_alloc_memery: - kfree(denali); + denali_irq_cleanup(denali->irq, denali); + return ret; } +EXPORT_SYMBOL(denali_init); /* driver exit point */ -static void denali_pci_remove(struct pci_dev *dev) +void denali_remove(struct denali_nand_info *denali) { - struct denali_nand_info *denali = pci_get_drvdata(dev); - - nand_release(&denali->mtd); - - denali_irq_cleanup(dev->irq, denali); - - iounmap(denali->flash_reg); - iounmap(denali->flash_mem); - pci_release_regions(dev); - pci_disable_device(dev); - dma_unmap_single(&dev->dev, denali->buf.dma_buf, DENALI_BUF_SIZE, - DMA_BIDIRECTIONAL); - pci_set_drvdata(dev, NULL); - kfree(denali); + denali_irq_cleanup(denali->irq, denali); + dma_unmap_single(denali->dev, denali->buf.dma_buf, DENALI_BUF_SIZE, + DMA_BIDIRECTIONAL); } - -MODULE_DEVICE_TABLE(pci, denali_pci_ids); - -static struct pci_driver denali_pci_driver = { - .name = DENALI_NAND_NAME, - .id_table = denali_pci_ids, - .probe = denali_pci_probe, - .remove = denali_pci_remove, -}; - -module_pci_driver(denali_pci_driver); +EXPORT_SYMBOL(denali_remove); diff --git a/drivers/mtd/nand/denali.h b/drivers/mtd/nand/denali.h index fabb9d56b39e..cec5712862c9 100644 --- a/drivers/mtd/nand/denali.h +++ b/drivers/mtd/nand/denali.h @@ -466,6 +466,7 @@ struct nand_buf { #define INTEL_CE4100 1 #define INTEL_MRST 2 +#define DT 3 struct denali_nand_info { struct mtd_info mtd; @@ -487,6 +488,7 @@ struct denali_nand_info { uint32_t irq_status; int irq_debug_array[32]; int idx; + int irq; uint32_t devnum; /* represent how many nands connected */ uint32_t fwblks; /* represent how many blocks FW used */ @@ -496,4 +498,7 @@ struct denali_nand_info { uint32_t max_banks; }; +extern int denali_init(struct denali_nand_info *denali); +extern void denali_remove(struct denali_nand_info *denali); + #endif /*_LLD_NAND_*/ diff --git a/drivers/mtd/nand/denali_dt.c b/drivers/mtd/nand/denali_dt.c new file mode 100644 index 000000000000..546f8cb5688d --- /dev/null +++ b/drivers/mtd/nand/denali_dt.c @@ -0,0 +1,167 @@ +/* + * NAND Flash Controller Device Driver for DT + * + * Copyright © 2011, Picochip. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ +#include <linux/clk.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/ioport.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/slab.h> + +#include "denali.h" + +struct denali_dt { + struct denali_nand_info denali; + struct clk *clk; +}; + +static void __iomem *request_and_map(struct device *dev, + const struct resource *res) +{ + void __iomem *ptr; + + if (!devm_request_mem_region(dev, res->start, resource_size(res), + "denali-dt")) { + dev_err(dev, "unable to request %s\n", res->name); + return NULL; + } + + ptr = devm_ioremap_nocache(dev, res->start, resource_size(res)); + if (!res) + dev_err(dev, "ioremap_nocache of %s failed!", res->name); + + return ptr; +} + +static const struct of_device_id denali_nand_dt_ids[] = { + { .compatible = "denali,denali-nand-dt" }, + { /* sentinel */ } + }; + +MODULE_DEVICE_TABLE(of, denali_nand_dt_ids); + +static u64 denali_dma_mask; + +static int denali_dt_probe(struct platform_device *ofdev) +{ + struct resource *denali_reg, *nand_data; + struct denali_dt *dt; + struct denali_nand_info *denali; + int ret; + const struct of_device_id *of_id; + + of_id = of_match_device(denali_nand_dt_ids, &ofdev->dev); + if (of_id) { + ofdev->id_entry = of_id->data; + } else { + pr_err("Failed to find the right device id.\n"); + return -ENOMEM; + } + + dt = devm_kzalloc(&ofdev->dev, sizeof(*dt), GFP_KERNEL); + if (!dt) + return -ENOMEM; + denali = &dt->denali; + + denali_reg = platform_get_resource_byname(ofdev, IORESOURCE_MEM, "denali_reg"); + nand_data = platform_get_resource_byname(ofdev, IORESOURCE_MEM, "nand_data"); + if (!denali_reg || !nand_data) { + dev_err(&ofdev->dev, "resources not completely defined\n"); + return -EINVAL; + } + + denali->platform = DT; + denali->dev = &ofdev->dev; + denali->irq = platform_get_irq(ofdev, 0); + if (denali->irq < 0) { + dev_err(&ofdev->dev, "no irq defined\n"); + return -ENXIO; + } + + denali->flash_reg = request_and_map(&ofdev->dev, denali_reg); + if (!denali->flash_reg) + return -ENOMEM; + + denali->flash_mem = request_and_map(&ofdev->dev, nand_data); + if (!denali->flash_mem) + return -ENOMEM; + + if (!of_property_read_u32(ofdev->dev.of_node, + "dma-mask", (u32 *)&denali_dma_mask)) { + denali->dev->dma_mask = &denali_dma_mask; + } else { + denali->dev->dma_mask = NULL; + } + + dt->clk = clk_get(&ofdev->dev, NULL); + if (IS_ERR(dt->clk)) { + dev_err(&ofdev->dev, "no clk available\n"); + return PTR_ERR(dt->clk); + } + clk_prepare_enable(dt->clk); + + ret = denali_init(denali); + if (ret) + goto out_disable_clk; + + platform_set_drvdata(ofdev, dt); + return 0; + +out_disable_clk: + clk_disable_unprepare(dt->clk); + clk_put(dt->clk); + + return ret; +} + +static int denali_dt_remove(struct platform_device *ofdev) +{ + struct denali_dt *dt = platform_get_drvdata(ofdev); + + denali_remove(&dt->denali); + clk_disable(dt->clk); + clk_put(dt->clk); + + return 0; +} + +static struct platform_driver denali_dt_driver = { + .probe = denali_dt_probe, + .remove = denali_dt_remove, + .driver = { + .name = "denali-nand-dt", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(denali_nand_dt_ids), + }, +}; + +static int __init denali_init_dt(void) +{ + return platform_driver_register(&denali_dt_driver); +} +module_init(denali_init_dt); + +static void __exit denali_exit_dt(void) +{ + platform_driver_unregister(&denali_dt_driver); +} +module_exit(denali_exit_dt); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Jamie Iles"); +MODULE_DESCRIPTION("DT driver for Denali NAND controller"); diff --git a/drivers/mtd/nand/denali_pci.c b/drivers/mtd/nand/denali_pci.c new file mode 100644 index 000000000000..e3e46623b2b4 --- /dev/null +++ b/drivers/mtd/nand/denali_pci.c @@ -0,0 +1,144 @@ +/* + * NAND Flash Controller Device Driver + * Copyright © 2009-2010, Intel Corporation and its suppliers. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/pci.h> +#include <linux/slab.h> + +#include "denali.h" + +#define DENALI_NAND_NAME "denali-nand-pci" + +/* List of platforms this NAND controller has be integrated into */ +static DEFINE_PCI_DEVICE_TABLE(denali_pci_ids) = { + { PCI_VDEVICE(INTEL, 0x0701), INTEL_CE4100 }, + { PCI_VDEVICE(INTEL, 0x0809), INTEL_MRST }, + { /* end: all zeroes */ } +}; +MODULE_DEVICE_TABLE(pci, denali_pci_ids); + +static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) +{ + int ret = -ENODEV; + resource_size_t csr_base, mem_base; + unsigned long csr_len, mem_len; + struct denali_nand_info *denali; + + denali = kzalloc(sizeof(*denali), GFP_KERNEL); + if (!denali) + return -ENOMEM; + + ret = pci_enable_device(dev); + if (ret) { + pr_err("Spectra: pci_enable_device failed.\n"); + goto failed_alloc_memery; + } + + if (id->driver_data == INTEL_CE4100) { + denali->platform = INTEL_CE4100; + mem_base = pci_resource_start(dev, 0); + mem_len = pci_resource_len(dev, 1); + csr_base = pci_resource_start(dev, 1); + csr_len = pci_resource_len(dev, 1); + } else { + denali->platform = INTEL_MRST; + csr_base = pci_resource_start(dev, 0); + csr_len = pci_resource_len(dev, 0); + mem_base = pci_resource_start(dev, 1); + mem_len = pci_resource_len(dev, 1); + if (!mem_len) { + mem_base = csr_base + csr_len; + mem_len = csr_len; + } + } + + pci_set_master(dev); + denali->dev = &dev->dev; + denali->irq = dev->irq; + + ret = pci_request_regions(dev, DENALI_NAND_NAME); + if (ret) { + pr_err("Spectra: Unable to request memory regions\n"); + goto failed_enable_dev; + } + + denali->flash_reg = ioremap_nocache(csr_base, csr_len); + if (!denali->flash_reg) { + pr_err("Spectra: Unable to remap memory region\n"); + ret = -ENOMEM; + goto failed_req_regions; + } + + denali->flash_mem = ioremap_nocache(mem_base, mem_len); + if (!denali->flash_mem) { + pr_err("Spectra: ioremap_nocache failed!"); + ret = -ENOMEM; + goto failed_remap_reg; + } + + ret = denali_init(denali); + if (ret) + goto failed_remap_mem; + + pci_set_drvdata(dev, denali); + + return 0; + +failed_remap_mem: + iounmap(denali->flash_mem); +failed_remap_reg: + iounmap(denali->flash_reg); +failed_req_regions: + pci_release_regions(dev); +failed_enable_dev: + pci_disable_device(dev); +failed_alloc_memery: + kfree(denali); + + return ret; +} + +/* driver exit point */ +static void denali_pci_remove(struct pci_dev *dev) +{ + struct denali_nand_info *denali = pci_get_drvdata(dev); + + denali_remove(denali); + iounmap(denali->flash_reg); + iounmap(denali->flash_mem); + pci_release_regions(dev); + pci_disable_device(dev); + pci_set_drvdata(dev, NULL); + kfree(denali); +} + +static struct pci_driver denali_pci_driver = { + .name = DENALI_NAND_NAME, + .id_table = denali_pci_ids, + .probe = denali_pci_probe, + .remove = denali_pci_remove, +}; + +static int denali_init_pci(void) +{ + pr_info("Spectra MTD driver built on %s @ %s\n", __DATE__, __TIME__); + return pci_register_driver(&denali_pci_driver); +} +module_init(denali_init_pci); + +static void denali_exit_pci(void) +{ + pci_unregister_driver(&denali_pci_driver); +} +module_exit(denali_exit_pci); diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c index 256eb30f6180..81fa5784f98b 100644 --- a/drivers/mtd/nand/diskonchip.c +++ b/drivers/mtd/nand/diskonchip.c @@ -53,8 +53,6 @@ static unsigned long __initdata doc_locations[] = { 0xe0000, 0xe2000, 0xe4000, 0xe6000, 0xe8000, 0xea000, 0xec000, 0xee000, #endif /* CONFIG_MTD_DOCPROBE_HIGH */ -#else -#warning Unknown architecture for DiskOnChip. No default probe locations defined #endif 0xffffffff }; diff --git a/drivers/mtd/nand/docg4.c b/drivers/mtd/nand/docg4.c index 799da5d1c857..18fa4489e52e 100644 --- a/drivers/mtd/nand/docg4.c +++ b/drivers/mtd/nand/docg4.c @@ -46,6 +46,25 @@ #include <linux/bitrev.h> /* + * In "reliable mode" consecutive 2k pages are used in parallel (in some + * fashion) to store the same data. The data can be read back from the + * even-numbered pages in the normal manner; odd-numbered pages will appear to + * contain junk. Systems that boot from the docg4 typically write the secondary + * program loader (SPL) code in this mode. The SPL is loaded by the initial + * program loader (IPL, stored in the docg4's 2k NOR-like region that is mapped + * to the reset vector address). This module parameter enables you to use this + * driver to write the SPL. When in this mode, no more than 2k of data can be + * written at a time, because the addresses do not increment in the normal + * manner, and the starting offset must be within an even-numbered 2k region; + * i.e., invalid starting offsets are 0x800, 0xa00, 0xc00, 0xe00, 0x1800, + * 0x1a00, ... Reliable mode is a special case and should not be used unless + * you know what you're doing. + */ +static bool reliable_mode; +module_param(reliable_mode, bool, 0); +MODULE_PARM_DESC(reliable_mode, "pages are programmed in reliable mode"); + +/* * You'll want to ignore badblocks if you're reading a partition that contains * data written by the TrueFFS library (i.e., by PalmOS, Windows, etc), since * it does not use mtd nand's method for marking bad blocks (using oob area). @@ -113,6 +132,7 @@ struct docg4_priv { #define DOCG4_SEQ_PAGEWRITE 0x16 #define DOCG4_SEQ_PAGEPROG 0x1e #define DOCG4_SEQ_BLOCKERASE 0x24 +#define DOCG4_SEQ_SETMODE 0x45 /* DOC_FLASHCOMMAND register commands */ #define DOCG4_CMD_PAGE_READ 0x00 @@ -122,6 +142,8 @@ struct docg4_priv { #define DOC_CMD_PROG_BLOCK_ADDR 0x60 #define DOCG4_CMD_PAGEWRITE 0x80 #define DOC_CMD_PROG_CYCLE2 0x10 +#define DOCG4_CMD_FAST_MODE 0xa3 /* functionality guessed */ +#define DOC_CMD_RELIABLE_MODE 0x22 #define DOC_CMD_RESET 0xff /* DOC_POWERMODE register bits */ @@ -190,17 +212,20 @@ struct docg4_priv { #define DOCG4_T 4 /* BCH alg corrects up to 4 bit errors */ #define DOCG4_FACTORY_BBT_PAGE 16 /* page where read-only factory bbt lives */ +#define DOCG4_REDUNDANT_BBT_PAGE 24 /* page where redundant factory bbt lives */ /* - * Oob bytes 0 - 6 are available to the user. - * Byte 7 is hamming ecc for first 7 bytes. Bytes 8 - 14 are hw-generated ecc. + * Bytes 0, 1 are used as badblock marker. + * Bytes 2 - 6 are available to the user. + * Byte 7 is hamming ecc for first 7 oob bytes only. + * Bytes 8 - 14 are hw-generated ecc covering entire page + oob bytes 0 - 14. * Byte 15 (the last) is used by the driver as a "page written" flag. */ static struct nand_ecclayout docg4_oobinfo = { .eccbytes = 9, .eccpos = {7, 8, 9, 10, 11, 12, 13, 14, 15}, - .oobavail = 7, - .oobfree = { {0, 7} } + .oobavail = 5, + .oobfree = { {.offset = 2, .length = 5} } }; /* @@ -611,6 +636,14 @@ static void write_page_prologue(struct mtd_info *mtd, uint32_t docg4_addr) dev_dbg(doc->dev, "docg4: %s: g4 addr: %x\n", __func__, docg4_addr); sequence_reset(mtd); + + if (unlikely(reliable_mode)) { + writew(DOCG4_SEQ_SETMODE, docptr + DOC_FLASHSEQUENCE); + writew(DOCG4_CMD_FAST_MODE, docptr + DOC_FLASHCOMMAND); + writew(DOC_CMD_RELIABLE_MODE, docptr + DOC_FLASHCOMMAND); + write_nop(docptr); + } + writew(DOCG4_SEQ_PAGEWRITE, docptr + DOC_FLASHSEQUENCE); writew(DOCG4_CMD_PAGEWRITE, docptr + DOC_FLASHCOMMAND); write_nop(docptr); @@ -691,6 +724,15 @@ static void docg4_command(struct mtd_info *mtd, unsigned command, int column, break; case NAND_CMD_SEQIN: + if (unlikely(reliable_mode)) { + uint16_t g4_page = g4_addr >> 16; + + /* writes to odd-numbered 2k pages are invalid */ + if (g4_page & 0x01) + dev_warn(doc->dev, + "invalid reliable mode address\n"); + } + write_page_prologue(mtd, g4_addr); /* hack for deferred write of oob bytes */ @@ -979,16 +1021,15 @@ static int __init read_factory_bbt(struct mtd_info *mtd) struct docg4_priv *doc = nand->priv; uint32_t g4_addr = mtd_to_docg4_address(DOCG4_FACTORY_BBT_PAGE, 0); uint8_t *buf; - int i, block, status; + int i, block; + __u32 eccfailed_stats = mtd->ecc_stats.failed; buf = kzalloc(DOCG4_PAGE_SIZE, GFP_KERNEL); if (buf == NULL) return -ENOMEM; read_page_prologue(mtd, g4_addr); - status = docg4_read_page(mtd, nand, buf, 0, DOCG4_FACTORY_BBT_PAGE); - if (status) - goto exit; + docg4_read_page(mtd, nand, buf, 0, DOCG4_FACTORY_BBT_PAGE); /* * If no memory-based bbt was created, exit. This will happen if module @@ -1000,6 +1041,20 @@ static int __init read_factory_bbt(struct mtd_info *mtd) if (nand->bbt == NULL) /* no memory-based bbt */ goto exit; + if (mtd->ecc_stats.failed > eccfailed_stats) { + /* + * Whoops, an ecc failure ocurred reading the factory bbt. + * It is stored redundantly, so we get another chance. + */ + eccfailed_stats = mtd->ecc_stats.failed; + docg4_read_page(mtd, nand, buf, 0, DOCG4_REDUNDANT_BBT_PAGE); + if (mtd->ecc_stats.failed > eccfailed_stats) { + dev_warn(doc->dev, + "The factory bbt could not be read!\n"); + goto exit; + } + } + /* * Parse factory bbt and update memory-based bbt. Factory bbt format is * simple: one bit per block, block numbers increase left to right (msb @@ -1019,7 +1074,7 @@ static int __init read_factory_bbt(struct mtd_info *mtd) } exit: kfree(buf); - return status; + return 0; } static int docg4_block_markbad(struct mtd_info *mtd, loff_t ofs) diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c index cc1480a5e4c1..20657209a472 100644 --- a/drivers/mtd/nand/fsl_elbc_nand.c +++ b/drivers/mtd/nand/fsl_elbc_nand.c @@ -109,20 +109,6 @@ static struct nand_ecclayout fsl_elbc_oob_lp_eccm1 = { }; /* - * fsl_elbc_oob_lp_eccm* specify that LP NAND's OOB free area starts at offset - * 1, so we have to adjust bad block pattern. This pattern should be used for - * x8 chips only. So far hardware does not support x16 chips anyway. - */ -static u8 scan_ff_pattern[] = { 0xff, }; - -static struct nand_bbt_descr largepage_memorybased = { - .options = 0, - .offs = 0, - .len = 1, - .pattern = scan_ff_pattern, -}; - -/* * ELBC may use HW ECC, so that OOB offsets, that NAND core uses for bbt, * interfere with ECC positions, that's why we implement our own descriptors. * OOB {11, 5}, works for both SP and LP chips, with ECCM = 1 and ECCM = 0. @@ -699,7 +685,6 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd) chip->ecc.layout = (priv->fmr & FMR_ECCM) ? &fsl_elbc_oob_lp_eccm1 : &fsl_elbc_oob_lp_eccm0; - chip->badblock_pattern = &largepage_memorybased; } } else { dev_err(priv->dev, @@ -814,7 +799,7 @@ static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv) static DEFINE_MUTEX(fsl_elbc_nand_mutex); -static int __devinit fsl_elbc_nand_probe(struct platform_device *pdev) +static int fsl_elbc_nand_probe(struct platform_device *pdev) { struct fsl_lbc_regs __iomem *lbc; struct fsl_elbc_mtd *priv; diff --git a/drivers/mtd/nand/fsl_ifc_nand.c b/drivers/mtd/nand/fsl_ifc_nand.c index 3551a99076ba..ad6222627fed 100644 --- a/drivers/mtd/nand/fsl_ifc_nand.c +++ b/drivers/mtd/nand/fsl_ifc_nand.c @@ -389,7 +389,7 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command, timing = IFC_FIR_OP_RBCD; out_be32(&ifc->ifc_nand.nand_fir0, - (IFC_FIR_OP_CMD0 << IFC_NAND_FIR0_OP0_SHIFT) | + (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | (IFC_FIR_OP_UA << IFC_NAND_FIR0_OP1_SHIFT) | (timing << IFC_NAND_FIR0_OP2_SHIFT)); out_be32(&ifc->ifc_nand.nand_fcr0, @@ -754,7 +754,7 @@ static void fsl_ifc_sram_init(struct fsl_ifc_mtd *priv) /* READID */ out_be32(&ifc->ifc_nand.nand_fir0, - (IFC_FIR_OP_CMD0 << IFC_NAND_FIR0_OP0_SHIFT) | + (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | (IFC_FIR_OP_UA << IFC_NAND_FIR0_OP1_SHIFT) | (IFC_FIR_OP_RB << IFC_NAND_FIR0_OP2_SHIFT)); out_be32(&ifc->ifc_nand.nand_fcr0, @@ -922,7 +922,7 @@ static int match_bank(struct fsl_ifc_regs __iomem *ifc, int bank, static DEFINE_MUTEX(fsl_ifc_nand_mutex); -static int __devinit fsl_ifc_nand_probe(struct platform_device *dev) +static int fsl_ifc_nand_probe(struct platform_device *dev) { struct fsl_ifc_regs __iomem *ifc; struct fsl_ifc_mtd *priv; diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c index 45df542b9c61..5a8f5c4ce512 100644 --- a/drivers/mtd/nand/fsl_upm.c +++ b/drivers/mtd/nand/fsl_upm.c @@ -152,7 +152,7 @@ static void fun_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) fun_wait_rnb(fun); } -static int __devinit fun_chip_init(struct fsl_upm_nand *fun, +static int fun_chip_init(struct fsl_upm_nand *fun, const struct device_node *upm_np, const struct resource *io_res) { @@ -201,7 +201,7 @@ err: return ret; } -static int __devinit fun_probe(struct platform_device *ofdev) +static int fun_probe(struct platform_device *ofdev) { struct fsl_upm_nand *fun; struct resource io_res; @@ -318,7 +318,7 @@ err1: return ret; } -static int __devexit fun_remove(struct platform_device *ofdev) +static int fun_remove(struct platform_device *ofdev) { struct fsl_upm_nand *fun = dev_get_drvdata(&ofdev->dev); int i; @@ -350,7 +350,7 @@ static struct platform_driver of_fun_driver = { .of_match_table = of_fun_match, }, .probe = fun_probe, - .remove = __devexit_p(fun_remove), + .remove = fun_remove, }; module_platform_driver(of_fun_driver); diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c index 38d26240d8b1..1d7446434b0e 100644 --- a/drivers/mtd/nand/fsmc_nand.c +++ b/drivers/mtd/nand/fsmc_nand.c @@ -361,7 +361,7 @@ static void fsmc_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) struct nand_chip *this = mtd->priv; struct fsmc_nand_data *host = container_of(mtd, struct fsmc_nand_data, mtd); - void *__iomem *regs = host->regs_va; + void __iomem *regs = host->regs_va; unsigned int bank = host->bank; if (ctrl & NAND_CTRL_CHANGE) { @@ -383,13 +383,13 @@ static void fsmc_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) pc |= FSMC_ENABLE; else pc &= ~FSMC_ENABLE; - writel(pc, FSMC_NAND_REG(regs, bank, PC)); + writel_relaxed(pc, FSMC_NAND_REG(regs, bank, PC)); } mb(); if (cmd != NAND_CMD_NONE) - writeb(cmd, this->IO_ADDR_W); + writeb_relaxed(cmd, this->IO_ADDR_W); } /* @@ -426,14 +426,18 @@ static void fsmc_nand_setup(void __iomem *regs, uint32_t bank, tset = (tims->tset & FSMC_TSET_MASK) << FSMC_TSET_SHIFT; if (busw) - writel(value | FSMC_DEVWID_16, FSMC_NAND_REG(regs, bank, PC)); + writel_relaxed(value | FSMC_DEVWID_16, + FSMC_NAND_REG(regs, bank, PC)); else - writel(value | FSMC_DEVWID_8, FSMC_NAND_REG(regs, bank, PC)); + writel_relaxed(value | FSMC_DEVWID_8, + FSMC_NAND_REG(regs, bank, PC)); - writel(readl(FSMC_NAND_REG(regs, bank, PC)) | tclr | tar, + writel_relaxed(readl(FSMC_NAND_REG(regs, bank, PC)) | tclr | tar, FSMC_NAND_REG(regs, bank, PC)); - writel(thiz | thold | twait | tset, FSMC_NAND_REG(regs, bank, COMM)); - writel(thiz | thold | twait | tset, FSMC_NAND_REG(regs, bank, ATTRIB)); + writel_relaxed(thiz | thold | twait | tset, + FSMC_NAND_REG(regs, bank, COMM)); + writel_relaxed(thiz | thold | twait | tset, + FSMC_NAND_REG(regs, bank, ATTRIB)); } /* @@ -446,11 +450,11 @@ static void fsmc_enable_hwecc(struct mtd_info *mtd, int mode) void __iomem *regs = host->regs_va; uint32_t bank = host->bank; - writel(readl(FSMC_NAND_REG(regs, bank, PC)) & ~FSMC_ECCPLEN_256, + writel_relaxed(readl(FSMC_NAND_REG(regs, bank, PC)) & ~FSMC_ECCPLEN_256, FSMC_NAND_REG(regs, bank, PC)); - writel(readl(FSMC_NAND_REG(regs, bank, PC)) & ~FSMC_ECCEN, + writel_relaxed(readl(FSMC_NAND_REG(regs, bank, PC)) & ~FSMC_ECCEN, FSMC_NAND_REG(regs, bank, PC)); - writel(readl(FSMC_NAND_REG(regs, bank, PC)) | FSMC_ECCEN, + writel_relaxed(readl(FSMC_NAND_REG(regs, bank, PC)) | FSMC_ECCEN, FSMC_NAND_REG(regs, bank, PC)); } @@ -470,7 +474,7 @@ static int fsmc_read_hwecc_ecc4(struct mtd_info *mtd, const uint8_t *data, unsigned long deadline = jiffies + FSMC_BUSY_WAIT_TIMEOUT; do { - if (readl(FSMC_NAND_REG(regs, bank, STS)) & FSMC_CODE_RDY) + if (readl_relaxed(FSMC_NAND_REG(regs, bank, STS)) & FSMC_CODE_RDY) break; else cond_resched(); @@ -481,25 +485,25 @@ static int fsmc_read_hwecc_ecc4(struct mtd_info *mtd, const uint8_t *data, return -ETIMEDOUT; } - ecc_tmp = readl(FSMC_NAND_REG(regs, bank, ECC1)); + ecc_tmp = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC1)); ecc[0] = (uint8_t) (ecc_tmp >> 0); ecc[1] = (uint8_t) (ecc_tmp >> 8); ecc[2] = (uint8_t) (ecc_tmp >> 16); ecc[3] = (uint8_t) (ecc_tmp >> 24); - ecc_tmp = readl(FSMC_NAND_REG(regs, bank, ECC2)); + ecc_tmp = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC2)); ecc[4] = (uint8_t) (ecc_tmp >> 0); ecc[5] = (uint8_t) (ecc_tmp >> 8); ecc[6] = (uint8_t) (ecc_tmp >> 16); ecc[7] = (uint8_t) (ecc_tmp >> 24); - ecc_tmp = readl(FSMC_NAND_REG(regs, bank, ECC3)); + ecc_tmp = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC3)); ecc[8] = (uint8_t) (ecc_tmp >> 0); ecc[9] = (uint8_t) (ecc_tmp >> 8); ecc[10] = (uint8_t) (ecc_tmp >> 16); ecc[11] = (uint8_t) (ecc_tmp >> 24); - ecc_tmp = readl(FSMC_NAND_REG(regs, bank, STS)); + ecc_tmp = readl_relaxed(FSMC_NAND_REG(regs, bank, STS)); ecc[12] = (uint8_t) (ecc_tmp >> 16); return 0; @@ -519,7 +523,7 @@ static int fsmc_read_hwecc_ecc1(struct mtd_info *mtd, const uint8_t *data, uint32_t bank = host->bank; uint32_t ecc_tmp; - ecc_tmp = readl(FSMC_NAND_REG(regs, bank, ECC1)); + ecc_tmp = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC1)); ecc[0] = (uint8_t) (ecc_tmp >> 0); ecc[1] = (uint8_t) (ecc_tmp >> 8); ecc[2] = (uint8_t) (ecc_tmp >> 16); @@ -601,7 +605,7 @@ static int dma_xfer(struct fsmc_nand_data *host, void *buffer, int len, dma_async_issue_pending(chan); ret = - wait_for_completion_interruptible_timeout(&host->dma_access_complete, + wait_for_completion_timeout(&host->dma_access_complete, msecs_to_jiffies(3000)); if (ret <= 0) { chan->device->device_control(chan, DMA_TERMINATE_ALL, 0); @@ -628,10 +632,10 @@ static void fsmc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) uint32_t *p = (uint32_t *)buf; len = len >> 2; for (i = 0; i < len; i++) - writel(p[i], chip->IO_ADDR_W); + writel_relaxed(p[i], chip->IO_ADDR_W); } else { for (i = 0; i < len; i++) - writeb(buf[i], chip->IO_ADDR_W); + writeb_relaxed(buf[i], chip->IO_ADDR_W); } } @@ -651,10 +655,10 @@ static void fsmc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) uint32_t *p = (uint32_t *)buf; len = len >> 2; for (i = 0; i < len; i++) - p[i] = readl(chip->IO_ADDR_R); + p[i] = readl_relaxed(chip->IO_ADDR_R); } else { for (i = 0; i < len; i++) - buf[i] = readb(chip->IO_ADDR_R); + buf[i] = readb_relaxed(chip->IO_ADDR_R); } } @@ -783,7 +787,7 @@ static int fsmc_bch8_correct_data(struct mtd_info *mtd, uint8_t *dat, uint32_t num_err, i; uint32_t ecc1, ecc2, ecc3, ecc4; - num_err = (readl(FSMC_NAND_REG(regs, bank, STS)) >> 10) & 0xF; + num_err = (readl_relaxed(FSMC_NAND_REG(regs, bank, STS)) >> 10) & 0xF; /* no bit flipping */ if (likely(num_err == 0)) @@ -826,10 +830,10 @@ static int fsmc_bch8_correct_data(struct mtd_info *mtd, uint8_t *dat, * uint64_t array and error offset indexes are populated in err_idx * array */ - ecc1 = readl(FSMC_NAND_REG(regs, bank, ECC1)); - ecc2 = readl(FSMC_NAND_REG(regs, bank, ECC2)); - ecc3 = readl(FSMC_NAND_REG(regs, bank, ECC3)); - ecc4 = readl(FSMC_NAND_REG(regs, bank, STS)); + ecc1 = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC1)); + ecc2 = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC2)); + ecc3 = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC3)); + ecc4 = readl_relaxed(FSMC_NAND_REG(regs, bank, STS)); err_idx[0] = (ecc1 >> 0) & 0x1FFF; err_idx[1] = (ecc1 >> 13) & 0x1FFF; @@ -860,7 +864,7 @@ static bool filter(struct dma_chan *chan, void *slave) } #ifdef CONFIG_OF -static int __devinit fsmc_nand_probe_config_dt(struct platform_device *pdev, +static int fsmc_nand_probe_config_dt(struct platform_device *pdev, struct device_node *np) { struct fsmc_nand_platform_data *pdata = dev_get_platdata(&pdev->dev); @@ -876,15 +880,13 @@ static int __devinit fsmc_nand_probe_config_dt(struct platform_device *pdev, return -EINVAL; } } - of_property_read_u32(np, "st,ale-off", &pdata->ale_off); - of_property_read_u32(np, "st,cle-off", &pdata->cle_off); if (of_get_property(np, "nand-skip-bbtscan", NULL)) pdata->options = NAND_SKIP_BBTSCAN; return 0; } #else -static int __devinit fsmc_nand_probe_config_dt(struct platform_device *pdev, +static int fsmc_nand_probe_config_dt(struct platform_device *pdev, struct device_node *np) { return -ENOSYS; @@ -935,41 +937,28 @@ static int __init fsmc_nand_probe(struct platform_device *pdev) if (!res) return -EINVAL; - if (!devm_request_mem_region(&pdev->dev, res->start, resource_size(res), - pdev->name)) { - dev_err(&pdev->dev, "Failed to get memory data resourse\n"); - return -ENOENT; - } - - host->data_pa = (dma_addr_t)res->start; - host->data_va = devm_ioremap(&pdev->dev, res->start, - resource_size(res)); + host->data_va = devm_request_and_ioremap(&pdev->dev, res); if (!host->data_va) { dev_err(&pdev->dev, "data ioremap failed\n"); return -ENOMEM; } + host->data_pa = (dma_addr_t)res->start; - if (!devm_request_mem_region(&pdev->dev, res->start + pdata->ale_off, - resource_size(res), pdev->name)) { - dev_err(&pdev->dev, "Failed to get memory ale resourse\n"); - return -ENOENT; - } + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nand_addr"); + if (!res) + return -EINVAL; - host->addr_va = devm_ioremap(&pdev->dev, res->start + pdata->ale_off, - resource_size(res)); + host->addr_va = devm_request_and_ioremap(&pdev->dev, res); if (!host->addr_va) { dev_err(&pdev->dev, "ale ioremap failed\n"); return -ENOMEM; } - if (!devm_request_mem_region(&pdev->dev, res->start + pdata->cle_off, - resource_size(res), pdev->name)) { - dev_err(&pdev->dev, "Failed to get memory cle resourse\n"); - return -ENOENT; - } + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nand_cmd"); + if (!res) + return -EINVAL; - host->cmd_va = devm_ioremap(&pdev->dev, res->start + pdata->cle_off, - resource_size(res)); + host->cmd_va = devm_request_and_ioremap(&pdev->dev, res); if (!host->cmd_va) { dev_err(&pdev->dev, "ale ioremap failed\n"); return -ENOMEM; @@ -979,14 +968,7 @@ static int __init fsmc_nand_probe(struct platform_device *pdev) if (!res) return -EINVAL; - if (!devm_request_mem_region(&pdev->dev, res->start, resource_size(res), - pdev->name)) { - dev_err(&pdev->dev, "Failed to get memory regs resourse\n"); - return -ENOENT; - } - - host->regs_va = devm_ioremap(&pdev->dev, res->start, - resource_size(res)); + host->regs_va = devm_request_and_ioremap(&pdev->dev, res); if (!host->regs_va) { dev_err(&pdev->dev, "regs ioremap failed\n"); return -ENOMEM; diff --git a/drivers/mtd/nand/gpio.c b/drivers/mtd/nand/gpio.c index bc73bc5f2713..e789e3f51710 100644 --- a/drivers/mtd/nand/gpio.c +++ b/drivers/mtd/nand/gpio.c @@ -90,14 +90,14 @@ static void gpio_nand_writebuf(struct mtd_info *mtd, const u_char *buf, int len) { struct nand_chip *this = mtd->priv; - writesb(this->IO_ADDR_W, buf, len); + iowrite8_rep(this->IO_ADDR_W, buf, len); } static void gpio_nand_readbuf(struct mtd_info *mtd, u_char *buf, int len) { struct nand_chip *this = mtd->priv; - readsb(this->IO_ADDR_R, buf, len); + ioread8_rep(this->IO_ADDR_R, buf, len); } static void gpio_nand_writebuf16(struct mtd_info *mtd, const u_char *buf, @@ -106,7 +106,7 @@ static void gpio_nand_writebuf16(struct mtd_info *mtd, const u_char *buf, struct nand_chip *this = mtd->priv; if (IS_ALIGNED((unsigned long)buf, 2)) { - writesw(this->IO_ADDR_W, buf, len>>1); + iowrite16_rep(this->IO_ADDR_W, buf, len>>1); } else { int i; unsigned short *ptr = (unsigned short *)buf; @@ -121,7 +121,7 @@ static void gpio_nand_readbuf16(struct mtd_info *mtd, u_char *buf, int len) struct nand_chip *this = mtd->priv; if (IS_ALIGNED((unsigned long)buf, 2)) { - readsw(this->IO_ADDR_R, buf, len>>1); + ioread16_rep(this->IO_ADDR_R, buf, len>>1); } else { int i; unsigned short *ptr = (unsigned short *)buf; @@ -134,7 +134,11 @@ static void gpio_nand_readbuf16(struct mtd_info *mtd, u_char *buf, int len) static int gpio_nand_devready(struct mtd_info *mtd) { struct gpiomtd *gpiomtd = gpio_nand_getpriv(mtd); - return gpio_get_value(gpiomtd->plat.gpio_rdy); + + if (gpio_is_valid(gpiomtd->plat.gpio_rdy)) + return gpio_get_value(gpiomtd->plat.gpio_rdy); + + return 1; } #ifdef CONFIG_OF @@ -227,7 +231,7 @@ gpio_nand_get_io_sync(struct platform_device *pdev) return platform_get_resource(pdev, IORESOURCE_MEM, 1); } -static int __devexit gpio_nand_remove(struct platform_device *dev) +static int gpio_nand_remove(struct platform_device *dev) { struct gpiomtd *gpiomtd = platform_get_drvdata(dev); struct resource *res; @@ -252,7 +256,8 @@ static int __devexit gpio_nand_remove(struct platform_device *dev) gpio_free(gpiomtd->plat.gpio_nce); if (gpio_is_valid(gpiomtd->plat.gpio_nwp)) gpio_free(gpiomtd->plat.gpio_nwp); - gpio_free(gpiomtd->plat.gpio_rdy); + if (gpio_is_valid(gpiomtd->plat.gpio_rdy)) + gpio_free(gpiomtd->plat.gpio_rdy); kfree(gpiomtd); @@ -277,7 +282,7 @@ static void __iomem *request_and_remap(struct resource *res, size_t size, return ptr; } -static int __devinit gpio_nand_probe(struct platform_device *dev) +static int gpio_nand_probe(struct platform_device *dev) { struct gpiomtd *gpiomtd; struct nand_chip *this; @@ -336,10 +341,12 @@ static int __devinit gpio_nand_probe(struct platform_device *dev) if (ret) goto err_cle; gpio_direction_output(gpiomtd->plat.gpio_cle, 0); - ret = gpio_request(gpiomtd->plat.gpio_rdy, "NAND RDY"); - if (ret) - goto err_rdy; - gpio_direction_input(gpiomtd->plat.gpio_rdy); + if (gpio_is_valid(gpiomtd->plat.gpio_rdy)) { + ret = gpio_request(gpiomtd->plat.gpio_rdy, "NAND RDY"); + if (ret) + goto err_rdy; + gpio_direction_input(gpiomtd->plat.gpio_rdy); + } this->IO_ADDR_W = this->IO_ADDR_R; @@ -386,7 +393,8 @@ static int __devinit gpio_nand_probe(struct platform_device *dev) err_wp: if (gpio_is_valid(gpiomtd->plat.gpio_nwp)) gpio_set_value(gpiomtd->plat.gpio_nwp, 0); - gpio_free(gpiomtd->plat.gpio_rdy); + if (gpio_is_valid(gpiomtd->plat.gpio_rdy)) + gpio_free(gpiomtd->plat.gpio_rdy); err_rdy: gpio_free(gpiomtd->plat.gpio_cle); err_cle: diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c index 3502accd4bc3..d84699c7968e 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c +++ b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c @@ -18,7 +18,6 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include <linux/mtd/gpmi-nand.h> #include <linux/delay.h> #include <linux/clk.h> @@ -166,6 +165,15 @@ int gpmi_init(struct gpmi_nand_data *this) if (ret) goto err_out; + /* + * Reset BCH here, too. We got failures otherwise :( + * See later BCH reset for explanation of MX23 handling + */ + ret = gpmi_reset_block(r->bch_regs, GPMI_IS_MX23(this)); + if (ret) + goto err_out; + + /* Choose NAND mode. */ writel(BM_GPMI_CTRL1_GPMI_MODE, r->gpmi_regs + HW_GPMI_CTRL1_CLR); diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c index d79696b2f19b..5cd141f7bfc2 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c +++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c @@ -25,7 +25,6 @@ #include <linux/slab.h> #include <linux/interrupt.h> #include <linux/module.h> -#include <linux/mtd/gpmi-nand.h> #include <linux/mtd/partitions.h> #include <linux/pinctrl/consumer.h> #include <linux/of.h> @@ -33,6 +32,12 @@ #include <linux/of_mtd.h> #include "gpmi-nand.h" +/* Resource names for the GPMI NAND driver. */ +#define GPMI_NAND_GPMI_REGS_ADDR_RES_NAME "gpmi-nand" +#define GPMI_NAND_BCH_REGS_ADDR_RES_NAME "bch" +#define GPMI_NAND_BCH_INTERRUPT_RES_NAME "bch" +#define GPMI_NAND_DMA_INTERRUPT_RES_NAME "gpmi-dma" + /* add our owner bbt descriptor */ static uint8_t scan_ff_pattern[] = { 0xff }; static struct nand_bbt_descr gpmi_bbt_descr = { @@ -222,7 +227,7 @@ void prepare_data_dma(struct gpmi_nand_data *this, enum dma_data_direction dr) ret = dma_map_sg(this->dev, sgl, 1, dr); if (ret == 0) - pr_err("map failed.\n"); + pr_err("DMA mapping failed.\n"); this->direct_dma_map_ok = false; } @@ -314,7 +319,7 @@ int start_dma_with_bch_irq(struct gpmi_nand_data *this, return 0; } -static int __devinit +static int acquire_register_block(struct gpmi_nand_data *this, const char *res_name) { struct platform_device *pdev = this->pdev; @@ -355,7 +360,7 @@ static void release_register_block(struct gpmi_nand_data *this) res->bch_regs = NULL; } -static int __devinit +static int acquire_bch_irq(struct gpmi_nand_data *this, irq_handler_t irq_h) { struct platform_device *pdev = this->pdev; @@ -422,7 +427,7 @@ static void release_dma_channels(struct gpmi_nand_data *this) } } -static int __devinit acquire_dma_channels(struct gpmi_nand_data *this) +static int acquire_dma_channels(struct gpmi_nand_data *this) { struct platform_device *pdev = this->pdev; struct resource *r_dma; @@ -456,7 +461,7 @@ static int __devinit acquire_dma_channels(struct gpmi_nand_data *this) dma_chan = dma_request_channel(mask, gpmi_dma_filter, this); if (!dma_chan) { - pr_err("dma_request_channel failed.\n"); + pr_err("Failed to request DMA channel.\n"); goto acquire_err; } @@ -487,7 +492,7 @@ static char *extra_clks_for_mx6q[GPMI_CLK_MAX] = { "gpmi_apb", "gpmi_bch", "gpmi_bch_apb", "per1_bch", }; -static int __devinit gpmi_get_clks(struct gpmi_nand_data *this) +static int gpmi_get_clks(struct gpmi_nand_data *this) { struct resources *r = &this->resources; char **extra_clks = NULL; @@ -533,7 +538,7 @@ err_clock: return -ENOMEM; } -static int __devinit acquire_resources(struct gpmi_nand_data *this) +static int acquire_resources(struct gpmi_nand_data *this) { struct pinctrl *pinctrl; int ret; @@ -583,7 +588,7 @@ static void release_resources(struct gpmi_nand_data *this) release_dma_channels(this); } -static int __devinit init_hardware(struct gpmi_nand_data *this) +static int init_hardware(struct gpmi_nand_data *this) { int ret; @@ -625,7 +630,8 @@ static int read_page_prepare(struct gpmi_nand_data *this, length, DMA_FROM_DEVICE); if (dma_mapping_error(dev, dest_phys)) { if (alt_size < length) { - pr_err("Alternate buffer is too small\n"); + pr_err("%s, Alternate buffer is too small\n", + __func__); return -ENOMEM; } goto map_failed; @@ -675,7 +681,8 @@ static int send_page_prepare(struct gpmi_nand_data *this, DMA_TO_DEVICE); if (dma_mapping_error(dev, source_phys)) { if (alt_size < length) { - pr_err("Alternate buffer is too small\n"); + pr_err("%s, Alternate buffer is too small\n", + __func__); return -ENOMEM; } goto map_failed; @@ -763,7 +770,7 @@ static int gpmi_alloc_dma_buffer(struct gpmi_nand_data *this) error_alloc: gpmi_free_dma_buffer(this); - pr_err("allocate DMA buffer ret!!\n"); + pr_err("Error allocating DMA buffers!\n"); return -ENOMEM; } @@ -1474,7 +1481,7 @@ static int gpmi_set_geometry(struct gpmi_nand_data *this) /* Set up the NFC geometry which is used by BCH. */ ret = bch_set_geometry(this); if (ret) { - pr_err("set geometry ret : %d\n", ret); + pr_err("Error setting BCH geometry : %d\n", ret); return ret; } @@ -1535,7 +1542,7 @@ static void gpmi_nfc_exit(struct gpmi_nand_data *this) gpmi_free_dma_buffer(this); } -static int __devinit gpmi_nfc_init(struct gpmi_nand_data *this) +static int gpmi_nfc_init(struct gpmi_nand_data *this) { struct mtd_info *mtd = &this->mtd; struct nand_chip *chip = &this->nand; @@ -1618,7 +1625,7 @@ static const struct of_device_id gpmi_nand_id_table[] = { }; MODULE_DEVICE_TABLE(of, gpmi_nand_id_table); -static int __devinit gpmi_nand_probe(struct platform_device *pdev) +static int gpmi_nand_probe(struct platform_device *pdev) { struct gpmi_nand_data *this; const struct of_device_id *of_id; @@ -1668,7 +1675,7 @@ exit_acquire_resources: return ret; } -static int __devexit gpmi_nand_remove(struct platform_device *pdev) +static int gpmi_nand_remove(struct platform_device *pdev) { struct gpmi_nand_data *this = platform_get_drvdata(pdev); @@ -1685,7 +1692,7 @@ static struct platform_driver gpmi_nand_driver = { .of_match_table = gpmi_nand_id_table, }, .probe = gpmi_nand_probe, - .remove = __devexit_p(gpmi_nand_remove), + .remove = gpmi_nand_remove, .id_table = gpmi_ids, }; module_platform_driver(gpmi_nand_driver); diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.h b/drivers/mtd/nand/gpmi-nand/gpmi-nand.h index 7ac25c1e58f9..3d93a5e39090 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.h +++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.h @@ -130,7 +130,6 @@ struct gpmi_nand_data { /* System Interface */ struct device *dev; struct platform_device *pdev; - struct gpmi_nand_platform_data *pdata; /* Resources */ struct resources resources; diff --git a/drivers/mtd/nand/jz4740_nand.c b/drivers/mtd/nand/jz4740_nand.c index 100b6775e175..8d415f014e1d 100644 --- a/drivers/mtd/nand/jz4740_nand.c +++ b/drivers/mtd/nand/jz4740_nand.c @@ -316,13 +316,17 @@ err: return ret; } -static inline void jz_nand_iounmap_resource(struct resource *res, void __iomem *base) +static inline void jz_nand_iounmap_resource(struct resource *res, + void __iomem *base) { iounmap(base); release_mem_region(res->start, resource_size(res)); } -static int __devinit jz_nand_detect_bank(struct platform_device *pdev, struct jz_nand *nand, unsigned char bank, size_t chipnr, uint8_t *nand_maf_id, uint8_t *nand_dev_id) { +static int jz_nand_detect_bank(struct platform_device *pdev, + struct jz_nand *nand, unsigned char bank, + size_t chipnr, uint8_t *nand_maf_id, + uint8_t *nand_dev_id) { int ret; int gpio; char gpio_name[9]; @@ -400,7 +404,7 @@ notfound_gpio: return ret; } -static int __devinit jz_nand_probe(struct platform_device *pdev) +static int jz_nand_probe(struct platform_device *pdev) { int ret; struct jz_nand *nand; @@ -541,7 +545,7 @@ err_free: return ret; } -static int __devexit jz_nand_remove(struct platform_device *pdev) +static int jz_nand_remove(struct platform_device *pdev) { struct jz_nand *nand = platform_get_drvdata(pdev); struct jz_nand_platform_data *pdata = pdev->dev.platform_data; @@ -573,7 +577,7 @@ static int __devexit jz_nand_remove(struct platform_device *pdev) static struct platform_driver jz_nand_driver = { .probe = jz_nand_probe, - .remove = __devexit_p(jz_nand_remove), + .remove = jz_nand_remove, .driver = { .name = "jz4740-nand", .owner = THIS_MODULE, diff --git a/drivers/mtd/nand/lpc32xx_mlc.c b/drivers/mtd/nand/lpc32xx_mlc.c index c29b7ac1f6af..f182befa7360 100644 --- a/drivers/mtd/nand/lpc32xx_mlc.c +++ b/drivers/mtd/nand/lpc32xx_mlc.c @@ -655,7 +655,7 @@ static struct lpc32xx_nand_cfg_mlc *lpc32xx_parse_dt(struct device *dev) /* * Probe for NAND controller */ -static int __devinit lpc32xx_nand_probe(struct platform_device *pdev) +static int lpc32xx_nand_probe(struct platform_device *pdev) { struct lpc32xx_nand_host *host; struct mtd_info *mtd; @@ -845,7 +845,7 @@ err_exit1: /* * Remove NAND device */ -static int __devexit lpc32xx_nand_remove(struct platform_device *pdev) +static int lpc32xx_nand_remove(struct platform_device *pdev) { struct lpc32xx_nand_host *host = platform_get_drvdata(pdev); struct mtd_info *mtd = &host->mtd; @@ -907,7 +907,7 @@ MODULE_DEVICE_TABLE(of, lpc32xx_nand_match); static struct platform_driver lpc32xx_nand_driver = { .probe = lpc32xx_nand_probe, - .remove = __devexit_p(lpc32xx_nand_remove), + .remove = lpc32xx_nand_remove, .resume = lpc32xx_nand_resume, .suspend = lpc32xx_nand_suspend, .driver = { diff --git a/drivers/mtd/nand/lpc32xx_slc.c b/drivers/mtd/nand/lpc32xx_slc.c index 32409c45d479..030b78c62895 100644 --- a/drivers/mtd/nand/lpc32xx_slc.c +++ b/drivers/mtd/nand/lpc32xx_slc.c @@ -755,7 +755,7 @@ static struct lpc32xx_nand_cfg_slc *lpc32xx_parse_dt(struct device *dev) /* * Probe for NAND controller */ -static int __devinit lpc32xx_nand_probe(struct platform_device *pdev) +static int lpc32xx_nand_probe(struct platform_device *pdev) { struct lpc32xx_nand_host *host; struct mtd_info *mtd; @@ -949,7 +949,7 @@ err_exit1: /* * Remove NAND device. */ -static int __devexit lpc32xx_nand_remove(struct platform_device *pdev) +static int lpc32xx_nand_remove(struct platform_device *pdev) { uint32_t tmp; struct lpc32xx_nand_host *host = platform_get_drvdata(pdev); @@ -1021,7 +1021,7 @@ MODULE_DEVICE_TABLE(of, lpc32xx_nand_match); static struct platform_driver lpc32xx_nand_driver = { .probe = lpc32xx_nand_probe, - .remove = __devexit_p(lpc32xx_nand_remove), + .remove = lpc32xx_nand_remove, .resume = lpc32xx_nand_resume, .suspend = lpc32xx_nand_suspend, .driver = { diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c index f776c8577b8c..3c9cdcbc4cba 100644 --- a/drivers/mtd/nand/mpc5121_nfc.c +++ b/drivers/mtd/nand/mpc5121_nfc.c @@ -626,7 +626,7 @@ static void mpc5121_nfc_free(struct device *dev, struct mtd_info *mtd) iounmap(prv->csreg); } -static int __devinit mpc5121_nfc_probe(struct platform_device *op) +static int mpc5121_nfc_probe(struct platform_device *op) { struct device_node *rootnode, *dn = op->dev.of_node; struct device *dev = &op->dev; @@ -827,7 +827,7 @@ error: return retval; } -static int __devexit mpc5121_nfc_remove(struct platform_device *op) +static int mpc5121_nfc_remove(struct platform_device *op) { struct device *dev = &op->dev; struct mtd_info *mtd = dev_get_drvdata(dev); @@ -841,14 +841,14 @@ static int __devexit mpc5121_nfc_remove(struct platform_device *op) return 0; } -static struct of_device_id mpc5121_nfc_match[] __devinitdata = { +static struct of_device_id mpc5121_nfc_match[] = { { .compatible = "fsl,mpc5121-nfc", }, {}, }; static struct platform_driver mpc5121_nfc_driver = { .probe = mpc5121_nfc_probe, - .remove = __devexit_p(mpc5121_nfc_remove), + .remove = mpc5121_nfc_remove, .driver = { .name = DRV_NAME, .owner = THIS_MODULE, diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index 72e31d86030d..45204e41a028 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c @@ -37,15 +37,9 @@ #include <asm/mach/flash.h> #include <linux/platform_data/mtd-mxc_nand.h> -#include <mach/hardware.h> #define DRIVER_NAME "mxc_nand" -#define nfc_is_v21() (cpu_is_mx25() || cpu_is_mx35()) -#define nfc_is_v1() (cpu_is_mx31() || cpu_is_mx27() || cpu_is_mx21()) -#define nfc_is_v3_2a() cpu_is_mx51() -#define nfc_is_v3_2b() cpu_is_mx53() - /* Addresses for NFC registers */ #define NFC_V1_V2_BUF_SIZE (host->regs + 0x00) #define NFC_V1_V2_BUF_ADDR (host->regs + 0x04) @@ -272,7 +266,8 @@ static struct nand_ecclayout nandv2_hw_eccoob_4k = { } }; -static const char *part_probes[] = { "RedBoot", "cmdlinepart", "ofpart", NULL }; +static const char const *part_probes[] = { + "cmdlinepart", "RedBoot", "ofpart", NULL }; static void memcpy32_fromio(void *trg, const void __iomem *src, size_t size) { @@ -1283,6 +1278,53 @@ static const struct mxc_nand_devtype_data imx53_nand_devtype_data = { .ppb_shift = 8, }; +static inline int is_imx21_nfc(struct mxc_nand_host *host) +{ + return host->devtype_data == &imx21_nand_devtype_data; +} + +static inline int is_imx27_nfc(struct mxc_nand_host *host) +{ + return host->devtype_data == &imx27_nand_devtype_data; +} + +static inline int is_imx25_nfc(struct mxc_nand_host *host) +{ + return host->devtype_data == &imx25_nand_devtype_data; +} + +static inline int is_imx51_nfc(struct mxc_nand_host *host) +{ + return host->devtype_data == &imx51_nand_devtype_data; +} + +static inline int is_imx53_nfc(struct mxc_nand_host *host) +{ + return host->devtype_data == &imx53_nand_devtype_data; +} + +static struct platform_device_id mxcnd_devtype[] = { + { + .name = "imx21-nand", + .driver_data = (kernel_ulong_t) &imx21_nand_devtype_data, + }, { + .name = "imx27-nand", + .driver_data = (kernel_ulong_t) &imx27_nand_devtype_data, + }, { + .name = "imx25-nand", + .driver_data = (kernel_ulong_t) &imx25_nand_devtype_data, + }, { + .name = "imx51-nand", + .driver_data = (kernel_ulong_t) &imx51_nand_devtype_data, + }, { + .name = "imx53-nand", + .driver_data = (kernel_ulong_t) &imx53_nand_devtype_data, + }, { + /* sentinel */ + } +}; +MODULE_DEVICE_TABLE(platform, mxcnd_devtype); + #ifdef CONFIG_OF_MTD static const struct of_device_id mxcnd_dt_ids[] = { { @@ -1337,33 +1379,7 @@ static int __init mxcnd_probe_dt(struct mxc_nand_host *host) } #endif -static int __init mxcnd_probe_pdata(struct mxc_nand_host *host) -{ - struct mxc_nand_platform_data *pdata = host->dev->platform_data; - - if (!pdata) - return -ENODEV; - - host->pdata = *pdata; - - if (nfc_is_v1()) { - if (cpu_is_mx21()) - host->devtype_data = &imx21_nand_devtype_data; - else - host->devtype_data = &imx27_nand_devtype_data; - } else if (nfc_is_v21()) { - host->devtype_data = &imx25_nand_devtype_data; - } else if (nfc_is_v3_2a()) { - host->devtype_data = &imx51_nand_devtype_data; - } else if (nfc_is_v3_2b()) { - host->devtype_data = &imx53_nand_devtype_data; - } else - BUG(); - - return 0; -} - -static int __devinit mxcnd_probe(struct platform_device *pdev) +static int mxcnd_probe(struct platform_device *pdev) { struct nand_chip *this; struct mtd_info *mtd; @@ -1404,8 +1420,16 @@ static int __devinit mxcnd_probe(struct platform_device *pdev) return PTR_ERR(host->clk); err = mxcnd_probe_dt(host); - if (err > 0) - err = mxcnd_probe_pdata(host); + if (err > 0) { + struct mxc_nand_platform_data *pdata = pdev->dev.platform_data; + if (pdata) { + host->pdata = *pdata; + host->devtype_data = (struct mxc_nand_devtype_data *) + pdev->id_entry->driver_data; + } else { + err = -ENODEV; + } + } if (err < 0) return err; @@ -1494,7 +1518,7 @@ static int __devinit mxcnd_probe(struct platform_device *pdev) } /* first scan to find the device and get the page size */ - if (nand_scan_ident(mtd, nfc_is_v21() ? 4 : 1, NULL)) { + if (nand_scan_ident(mtd, is_imx25_nfc(host) ? 4 : 1, NULL)) { err = -ENXIO; goto escan; } @@ -1508,7 +1532,7 @@ static int __devinit mxcnd_probe(struct platform_device *pdev) this->ecc.layout = host->devtype_data->ecclayout_4k; if (this->ecc.mode == NAND_ECC_HW) { - if (nfc_is_v1()) + if (is_imx21_nfc(host) || is_imx27_nfc(host)) this->ecc.strength = 1; else this->ecc.strength = (host->eccsize == 4) ? 4 : 8; @@ -1533,12 +1557,13 @@ static int __devinit mxcnd_probe(struct platform_device *pdev) return 0; escan: - clk_disable_unprepare(host->clk); + if (host->clk_act) + clk_disable_unprepare(host->clk); return err; } -static int __devexit mxcnd_remove(struct platform_device *pdev) +static int mxcnd_remove(struct platform_device *pdev) { struct mxc_nand_host *host = platform_get_drvdata(pdev); @@ -1555,8 +1580,9 @@ static struct platform_driver mxcnd_driver = { .owner = THIS_MODULE, .of_match_table = of_match_ptr(mxcnd_dt_ids), }, + .id_table = mxcnd_devtype, .probe = mxcnd_probe, - .remove = __devexit_p(mxcnd_remove), + .remove = mxcnd_remove, }; module_platform_driver(mxcnd_driver); diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index ec6841d8e956..8323ac991ad1 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -93,8 +93,7 @@ static struct nand_ecclayout nand_oob_128 = { .length = 78} } }; -static int nand_get_device(struct nand_chip *chip, struct mtd_info *mtd, - int new_state); +static int nand_get_device(struct mtd_info *mtd, int new_state); static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops); @@ -130,15 +129,12 @@ static int check_offs_len(struct mtd_info *mtd, * nand_release_device - [GENERIC] release chip * @mtd: MTD device structure * - * Deselect, release chip lock and wake up anyone waiting on the device. + * Release chip lock and wake up anyone waiting on the device. */ static void nand_release_device(struct mtd_info *mtd) { struct nand_chip *chip = mtd->priv; - /* De-select the NAND device */ - chip->select_chip(mtd, -1); - /* Release the controller and the chip */ spin_lock(&chip->controller->lock); chip->controller->active = NULL; @@ -160,7 +156,7 @@ static uint8_t nand_read_byte(struct mtd_info *mtd) } /** - * nand_read_byte16 - [DEFAULT] read one byte endianess aware from the chip + * nand_read_byte16 - [DEFAULT] read one byte endianness aware from the chip * nand_read_byte16 - [DEFAULT] read one byte endianness aware from the chip * @mtd: MTD device structure * @@ -303,7 +299,7 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) if (getchip) { chipnr = (int)(ofs >> chip->chip_shift); - nand_get_device(chip, mtd, FL_READING); + nand_get_device(mtd, FL_READING); /* Select the NAND device */ chip->select_chip(mtd, chipnr); @@ -333,8 +329,10 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) i++; } while (!res && i < 2 && (chip->bbt_options & NAND_BBT_SCAN2NDPAGE)); - if (getchip) + if (getchip) { + chip->select_chip(mtd, -1); nand_release_device(mtd); + } return res; } @@ -383,7 +381,7 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs) struct mtd_oob_ops ops; loff_t wr_ofs = ofs; - nand_get_device(chip, mtd, FL_WRITING); + nand_get_device(mtd, FL_WRITING); ops.datbuf = NULL; ops.oobbuf = buf; @@ -492,7 +490,7 @@ static void panic_nand_wait_ready(struct mtd_info *mtd, unsigned long timeo) void nand_wait_ready(struct mtd_info *mtd) { struct nand_chip *chip = mtd->priv; - unsigned long timeo = jiffies + 2; + unsigned long timeo = jiffies + msecs_to_jiffies(20); /* 400ms timeout */ if (in_interrupt() || oops_in_progress) @@ -750,15 +748,15 @@ static void panic_nand_get_device(struct nand_chip *chip, /** * nand_get_device - [GENERIC] Get chip for selected access - * @chip: the nand chip descriptor * @mtd: MTD device structure * @new_state: the state which is requested * * Get the device and lock it for exclusive access */ static int -nand_get_device(struct nand_chip *chip, struct mtd_info *mtd, int new_state) +nand_get_device(struct mtd_info *mtd, int new_state) { + struct nand_chip *chip = mtd->priv; spinlock_t *lock = &chip->controller->lock; wait_queue_head_t *wq = &chip->controller->wq; DECLARE_WAITQUEUE(wait, current); @@ -865,6 +863,8 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip) led_trigger_event(nand_led_trigger, LED_OFF); status = (int)chip->read_byte(mtd); + /* This can happen if in case of timeout or buggy dev_ready */ + WARN_ON(!(status & NAND_STATUS_READY)); return status; } @@ -899,7 +899,7 @@ static int __nand_unlock(struct mtd_info *mtd, loff_t ofs, /* Call wait ready function */ status = chip->waitfunc(mtd, chip); /* See if device thinks it succeeded */ - if (status & 0x01) { + if (status & NAND_STATUS_FAIL) { pr_debug("%s: error status = 0x%08x\n", __func__, status); ret = -EIO; @@ -932,7 +932,7 @@ int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) if (ofs + len == mtd->size) len -= mtd->erasesize; - nand_get_device(chip, mtd, FL_UNLOCKING); + nand_get_device(mtd, FL_UNLOCKING); /* Shift to get chip number */ chipnr = ofs >> chip->chip_shift; @@ -950,6 +950,7 @@ int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) ret = __nand_unlock(mtd, ofs, len, 0); out: + chip->select_chip(mtd, -1); nand_release_device(mtd); return ret; @@ -981,7 +982,7 @@ int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) if (check_offs_len(mtd, ofs, len)) ret = -EINVAL; - nand_get_device(chip, mtd, FL_LOCKING); + nand_get_device(mtd, FL_LOCKING); /* Shift to get chip number */ chipnr = ofs >> chip->chip_shift; @@ -1004,7 +1005,7 @@ int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) /* Call wait ready function */ status = chip->waitfunc(mtd, chip); /* See if device thinks it succeeded */ - if (status & 0x01) { + if (status & NAND_STATUS_FAIL) { pr_debug("%s: error status = 0x%08x\n", __func__, status); ret = -EIO; @@ -1014,6 +1015,7 @@ int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) ret = __nand_unlock(mtd, ofs, len, 0x1); out: + chip->select_chip(mtd, -1); nand_release_device(mtd); return ret; @@ -1550,6 +1552,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, chip->select_chip(mtd, chipnr); } } + chip->select_chip(mtd, -1); ops->retlen = ops->len - (size_t) readlen; if (oob) @@ -1577,11 +1580,10 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, static int nand_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, uint8_t *buf) { - struct nand_chip *chip = mtd->priv; struct mtd_oob_ops ops; int ret; - nand_get_device(chip, mtd, FL_READING); + nand_get_device(mtd, FL_READING); ops.len = len; ops.datbuf = buf; ops.oobbuf = NULL; @@ -1804,6 +1806,7 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from, chip->select_chip(mtd, chipnr); } } + chip->select_chip(mtd, -1); ops->oobretlen = ops->ooblen - readlen; @@ -1827,7 +1830,6 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from, static int nand_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops) { - struct nand_chip *chip = mtd->priv; int ret = -ENOTSUPP; ops->retlen = 0; @@ -1839,7 +1841,7 @@ static int nand_read_oob(struct mtd_info *mtd, loff_t from, return -EINVAL; } - nand_get_device(chip, mtd, FL_READING); + nand_get_device(mtd, FL_READING); switch (ops->mode) { case MTD_OPS_PLACE_OOB: @@ -2186,8 +2188,10 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, chip->select_chip(mtd, chipnr); /* Check, if it is write protected */ - if (nand_check_wp(mtd)) - return -EIO; + if (nand_check_wp(mtd)) { + ret = -EIO; + goto err_out; + } realpage = (int)(to >> chip->page_shift); page = realpage & chip->pagemask; @@ -2199,8 +2203,10 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, chip->pagebuf = -1; /* Don't allow multipage oob writes with offset */ - if (oob && ops->ooboffs && (ops->ooboffs + ops->ooblen > oobmaxlen)) - return -EINVAL; + if (oob && ops->ooboffs && (ops->ooboffs + ops->ooblen > oobmaxlen)) { + ret = -EINVAL; + goto err_out; + } while (1) { int bytes = mtd->writesize; @@ -2251,6 +2257,9 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, ops->retlen = ops->len - writelen; if (unlikely(oob)) ops->oobretlen = ops->ooblen; + +err_out: + chip->select_chip(mtd, -1); return ret; } @@ -2302,11 +2311,10 @@ static int panic_nand_write(struct mtd_info *mtd, loff_t to, size_t len, static int nand_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const uint8_t *buf) { - struct nand_chip *chip = mtd->priv; struct mtd_oob_ops ops; int ret; - nand_get_device(chip, mtd, FL_WRITING); + nand_get_device(mtd, FL_WRITING); ops.len = len; ops.datbuf = (uint8_t *)buf; ops.oobbuf = NULL; @@ -2377,8 +2385,10 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1); /* Check, if it is write protected */ - if (nand_check_wp(mtd)) + if (nand_check_wp(mtd)) { + chip->select_chip(mtd, -1); return -EROFS; + } /* Invalidate the page cache, if we write to the cached page */ if (page == chip->pagebuf) @@ -2391,6 +2401,8 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, else status = chip->ecc.write_oob(mtd, chip, page & chip->pagemask); + chip->select_chip(mtd, -1); + if (status) return status; @@ -2408,7 +2420,6 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, static int nand_write_oob(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops) { - struct nand_chip *chip = mtd->priv; int ret = -ENOTSUPP; ops->retlen = 0; @@ -2420,7 +2431,7 @@ static int nand_write_oob(struct mtd_info *mtd, loff_t to, return -EINVAL; } - nand_get_device(chip, mtd, FL_WRITING); + nand_get_device(mtd, FL_WRITING); switch (ops->mode) { case MTD_OPS_PLACE_OOB: @@ -2513,7 +2524,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, return -EINVAL; /* Grab the lock and see if the device is available */ - nand_get_device(chip, mtd, FL_ERASING); + nand_get_device(mtd, FL_ERASING); /* Shift to get first page */ page = (int)(instr->addr >> chip->page_shift); @@ -2623,6 +2634,7 @@ erase_exit: ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO; /* Deselect and wake up anyone waiting on the device */ + chip->select_chip(mtd, -1); nand_release_device(mtd); /* Do call back function */ @@ -2658,12 +2670,10 @@ erase_exit: */ static void nand_sync(struct mtd_info *mtd) { - struct nand_chip *chip = mtd->priv; - pr_debug("%s: called\n", __func__); /* Grab the lock and see if the device is available */ - nand_get_device(chip, mtd, FL_SYNCING); + nand_get_device(mtd, FL_SYNCING); /* Release it and go back */ nand_release_device(mtd); } @@ -2749,9 +2759,7 @@ static int nand_onfi_get_features(struct mtd_info *mtd, struct nand_chip *chip, */ static int nand_suspend(struct mtd_info *mtd) { - struct nand_chip *chip = mtd->priv; - - return nand_get_device(chip, mtd, FL_PM_SUSPENDED); + return nand_get_device(mtd, FL_PM_SUSPENDED); } /** @@ -2849,6 +2857,8 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip, int i; int val; + /* ONFI need to be probed in 8 bits mode */ + WARN_ON(chip->options & NAND_BUSWIDTH_16); /* Try ONFI for unknown chip or LP */ chip->cmdfunc(mtd, NAND_CMD_READID, 0x20, -1); if (chip->read_byte(mtd) != 'O' || chip->read_byte(mtd) != 'N' || @@ -2913,7 +2923,7 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip, * * Check if an ID string is repeated within a given sequence of bytes at * specific repetition interval period (e.g., {0x20,0x01,0x7F,0x20} has a - * period of 2). This is a helper function for nand_id_len(). Returns non-zero + * period of 3). This is a helper function for nand_id_len(). Returns non-zero * if the repetition has a period of @period; otherwise, returns zero. */ static int nand_id_has_period(u8 *id_data, int arrlen, int period) @@ -2983,13 +2993,15 @@ static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip, /* * Field definitions are in the following datasheets: * Old style (4,5 byte ID): Samsung K9GAG08U0M (p.32) - * New style (6 byte ID): Samsung K9GAG08U0F (p.44) + * New Samsung (6 byte ID): Samsung K9GAG08U0F (p.44) * Hynix MLC (6 byte ID): Hynix H27UBG8T2B (p.22) * - * Check for ID length, cell type, and Hynix/Samsung ID to decide what - * to do. + * Check for ID length, non-zero 6th byte, cell type, and Hynix/Samsung + * ID to decide what to do. */ - if (id_len == 6 && id_data[0] == NAND_MFR_SAMSUNG) { + if (id_len == 6 && id_data[0] == NAND_MFR_SAMSUNG && + (chip->cellinfo & NAND_CI_CELLTYPE_MSK) && + id_data[5] != 0x00) { /* Calc pagesize */ mtd->writesize = 2048 << (extid & 0x03); extid >>= 2; @@ -3240,11 +3252,15 @@ ident_done: break; } - /* - * Check, if buswidth is correct. Hardware drivers should set - * chip correct! - */ - if (busw != (chip->options & NAND_BUSWIDTH_16)) { + if (chip->options & NAND_BUSWIDTH_AUTO) { + WARN_ON(chip->options & NAND_BUSWIDTH_16); + chip->options |= busw; + nand_set_defaults(chip, busw); + } else if (busw != (chip->options & NAND_BUSWIDTH_16)) { + /* + * Check, if buswidth is correct. Hardware drivers should set + * chip correct! + */ pr_info("NAND device: Manufacturer ID:" " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, *dev_id, nand_manuf_ids[maf_idx].name, mtd->name); @@ -3283,10 +3299,10 @@ ident_done: chip->cmdfunc = nand_command_lp; pr_info("NAND device: Manufacturer ID: 0x%02x, Chip ID: 0x%02x (%s %s)," - " page size: %d, OOB size: %d\n", + " %dMiB, page size: %d, OOB size: %d\n", *maf_id, *dev_id, nand_manuf_ids[maf_idx].name, chip->onfi_version ? chip->onfi_params.model : type->name, - mtd->writesize, mtd->oobsize); + (int)(chip->chipsize >> 20), mtd->writesize, mtd->oobsize); return type; } @@ -3325,6 +3341,8 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips, return PTR_ERR(type); } + chip->select_chip(mtd, -1); + /* Check for a chip array */ for (i = 1; i < maxchips; i++) { chip->select_chip(mtd, i); @@ -3334,8 +3352,11 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips, chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); /* Read manufacturer and device IDs */ if (nand_maf_id != chip->read_byte(mtd) || - nand_dev_id != chip->read_byte(mtd)) + nand_dev_id != chip->read_byte(mtd)) { + chip->select_chip(mtd, -1); break; + } + chip->select_chip(mtd, -1); } if (i > 1) pr_info("%d NAND chips detected\n", i); @@ -3594,9 +3615,6 @@ int nand_scan_tail(struct mtd_info *mtd) /* Initialize state */ chip->state = FL_READY; - /* De-select the device */ - chip->select_chip(mtd, -1); - /* Invalidate the pagebuffer reference */ chip->pagebuf = -1; diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c index a932c485eb04..818b65c85d12 100644 --- a/drivers/mtd/nand/nandsim.c +++ b/drivers/mtd/nand/nandsim.c @@ -42,6 +42,8 @@ #include <linux/sched.h> #include <linux/fs.h> #include <linux/pagemap.h> +#include <linux/seq_file.h> +#include <linux/debugfs.h> /* Default simulator parameters values */ #if !defined(CONFIG_NANDSIM_FIRST_ID_BYTE) || \ @@ -105,7 +107,6 @@ static char *weakblocks = NULL; static char *weakpages = NULL; static unsigned int bitflips = 0; static char *gravepages = NULL; -static unsigned int rptwear = 0; static unsigned int overridesize = 0; static char *cache_file = NULL; static unsigned int bbt; @@ -130,7 +131,6 @@ module_param(weakblocks, charp, 0400); module_param(weakpages, charp, 0400); module_param(bitflips, uint, 0400); module_param(gravepages, charp, 0400); -module_param(rptwear, uint, 0400); module_param(overridesize, uint, 0400); module_param(cache_file, charp, 0400); module_param(bbt, uint, 0400); @@ -162,7 +162,6 @@ MODULE_PARM_DESC(bitflips, "Maximum number of random bit flips per page (z MODULE_PARM_DESC(gravepages, "Pages that lose data [: maximum reads (defaults to 3)]" " separated by commas e.g. 1401:2 means page 1401" " can be read only twice before failing"); -MODULE_PARM_DESC(rptwear, "Number of erases between reporting wear, if not zero"); MODULE_PARM_DESC(overridesize, "Specifies the NAND Flash size overriding the ID bytes. " "The size is specified in erase blocks and as the exponent of a power of two" " e.g. 5 means a size of 32 erase blocks"); @@ -286,6 +285,11 @@ MODULE_PARM_DESC(bch, "Enable BCH ecc and set how many bits should " /* Maximum page cache pages needed to read or write a NAND page to the cache_file */ #define NS_MAX_HELD_PAGES 16 +struct nandsim_debug_info { + struct dentry *dfs_root; + struct dentry *dfs_wear_report; +}; + /* * A union to represent flash memory contents and flash buffer. */ @@ -365,6 +369,8 @@ struct nandsim { void *file_buf; struct page *held_pages[NS_MAX_HELD_PAGES]; int held_cnt; + + struct nandsim_debug_info dbg; }; /* @@ -442,11 +448,123 @@ static LIST_HEAD(grave_pages); static unsigned long *erase_block_wear = NULL; static unsigned int wear_eb_count = 0; static unsigned long total_wear = 0; -static unsigned int rptwear_cnt = 0; /* MTD structure for NAND controller */ static struct mtd_info *nsmtd; +static int nandsim_debugfs_show(struct seq_file *m, void *private) +{ + unsigned long wmin = -1, wmax = 0, avg; + unsigned long deciles[10], decile_max[10], tot = 0; + unsigned int i; + + /* Calc wear stats */ + for (i = 0; i < wear_eb_count; ++i) { + unsigned long wear = erase_block_wear[i]; + if (wear < wmin) + wmin = wear; + if (wear > wmax) + wmax = wear; + tot += wear; + } + + for (i = 0; i < 9; ++i) { + deciles[i] = 0; + decile_max[i] = (wmax * (i + 1) + 5) / 10; + } + deciles[9] = 0; + decile_max[9] = wmax; + for (i = 0; i < wear_eb_count; ++i) { + int d; + unsigned long wear = erase_block_wear[i]; + for (d = 0; d < 10; ++d) + if (wear <= decile_max[d]) { + deciles[d] += 1; + break; + } + } + avg = tot / wear_eb_count; + + /* Output wear report */ + seq_printf(m, "Total numbers of erases: %lu\n", tot); + seq_printf(m, "Number of erase blocks: %u\n", wear_eb_count); + seq_printf(m, "Average number of erases: %lu\n", avg); + seq_printf(m, "Maximum number of erases: %lu\n", wmax); + seq_printf(m, "Minimum number of erases: %lu\n", wmin); + for (i = 0; i < 10; ++i) { + unsigned long from = (i ? decile_max[i - 1] + 1 : 0); + if (from > decile_max[i]) + continue; + seq_printf(m, "Number of ebs with erase counts from %lu to %lu : %lu\n", + from, + decile_max[i], + deciles[i]); + } + + return 0; +} + +static int nandsim_debugfs_open(struct inode *inode, struct file *file) +{ + return single_open(file, nandsim_debugfs_show, inode->i_private); +} + +static const struct file_operations dfs_fops = { + .open = nandsim_debugfs_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +/** + * nandsim_debugfs_create - initialize debugfs + * @dev: nandsim device description object + * + * This function creates all debugfs files for UBI device @ubi. Returns zero in + * case of success and a negative error code in case of failure. + */ +static int nandsim_debugfs_create(struct nandsim *dev) +{ + struct nandsim_debug_info *dbg = &dev->dbg; + struct dentry *dent; + int err; + + if (!IS_ENABLED(CONFIG_DEBUG_FS)) + return 0; + + dent = debugfs_create_dir("nandsim", NULL); + if (IS_ERR_OR_NULL(dent)) { + int err = dent ? -ENODEV : PTR_ERR(dent); + + NS_ERR("cannot create \"nandsim\" debugfs directory, err %d\n", + err); + return err; + } + dbg->dfs_root = dent; + + dent = debugfs_create_file("wear_report", S_IRUSR, + dbg->dfs_root, dev, &dfs_fops); + if (IS_ERR_OR_NULL(dent)) + goto out_remove; + dbg->dfs_wear_report = dent; + + return 0; + +out_remove: + debugfs_remove_recursive(dbg->dfs_root); + err = dent ? PTR_ERR(dent) : -ENODEV; + return err; +} + +/** + * nandsim_debugfs_remove - destroy all debugfs files + */ +static void nandsim_debugfs_remove(struct nandsim *ns) +{ + if (IS_ENABLED(CONFIG_DEBUG_FS)) + debugfs_remove_recursive(ns->dbg.dfs_root); +} + /* * Allocate array of page pointers, create slab allocation for an array * and initialize the array by NULL pointers. @@ -911,8 +1029,6 @@ static int setup_wear_reporting(struct mtd_info *mtd) { size_t mem; - if (!rptwear) - return 0; wear_eb_count = div_u64(mtd->size, mtd->erasesize); mem = wear_eb_count * sizeof(unsigned long); if (mem / sizeof(unsigned long) != wear_eb_count) { @@ -929,64 +1045,18 @@ static int setup_wear_reporting(struct mtd_info *mtd) static void update_wear(unsigned int erase_block_no) { - unsigned long wmin = -1, wmax = 0, avg; - unsigned long deciles[10], decile_max[10], tot = 0; - unsigned int i; - if (!erase_block_wear) return; total_wear += 1; + /* + * TODO: Notify this through a debugfs entry, + * instead of showing an error message. + */ if (total_wear == 0) NS_ERR("Erase counter total overflow\n"); erase_block_wear[erase_block_no] += 1; if (erase_block_wear[erase_block_no] == 0) NS_ERR("Erase counter overflow for erase block %u\n", erase_block_no); - rptwear_cnt += 1; - if (rptwear_cnt < rptwear) - return; - rptwear_cnt = 0; - /* Calc wear stats */ - for (i = 0; i < wear_eb_count; ++i) { - unsigned long wear = erase_block_wear[i]; - if (wear < wmin) - wmin = wear; - if (wear > wmax) - wmax = wear; - tot += wear; - } - for (i = 0; i < 9; ++i) { - deciles[i] = 0; - decile_max[i] = (wmax * (i + 1) + 5) / 10; - } - deciles[9] = 0; - decile_max[9] = wmax; - for (i = 0; i < wear_eb_count; ++i) { - int d; - unsigned long wear = erase_block_wear[i]; - for (d = 0; d < 10; ++d) - if (wear <= decile_max[d]) { - deciles[d] += 1; - break; - } - } - avg = tot / wear_eb_count; - /* Output wear report */ - NS_INFO("*** Wear Report ***\n"); - NS_INFO("Total numbers of erases: %lu\n", tot); - NS_INFO("Number of erase blocks: %u\n", wear_eb_count); - NS_INFO("Average number of erases: %lu\n", avg); - NS_INFO("Maximum number of erases: %lu\n", wmax); - NS_INFO("Minimum number of erases: %lu\n", wmin); - for (i = 0; i < 10; ++i) { - unsigned long from = (i ? decile_max[i - 1] + 1 : 0); - if (from > decile_max[i]) - continue; - NS_INFO("Number of ebs with erase counts from %lu to %lu : %lu\n", - from, - decile_max[i], - deciles[i]); - } - NS_INFO("*** End of Wear Report ***\n"); } /* @@ -1397,10 +1467,7 @@ int do_read_error(struct nandsim *ns, int num) unsigned int page_no = ns->regs.row; if (read_error(page_no)) { - int i; - memset(ns->buf.byte, 0xFF, num); - for (i = 0; i < num; ++i) - ns->buf.byte[i] = random32(); + prandom_bytes(ns->buf.byte, num); NS_WARN("simulating read error in page %u\n", page_no); return 1; } @@ -2330,6 +2397,9 @@ static int __init ns_init_module(void) if ((retval = setup_wear_reporting(nsmtd)) != 0) goto err_exit; + if ((retval = nandsim_debugfs_create(nand)) != 0) + goto err_exit; + if ((retval = init_nandsim(nsmtd)) != 0) goto err_exit; @@ -2369,6 +2439,7 @@ static void __exit ns_cleanup_module(void) struct nandsim *ns = ((struct nand_chip *)nsmtd->priv)->priv; int i; + nandsim_debugfs_remove(ns); free_nandsim(ns); /* Free nandsim private resources */ nand_release(nsmtd); /* Unregister driver */ for (i = 0;i < ARRAY_SIZE(ns->partitions); ++i) diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c index 5fd3f010e3ae..8e148f1478fd 100644 --- a/drivers/mtd/nand/ndfc.c +++ b/drivers/mtd/nand/ndfc.c @@ -197,7 +197,7 @@ err: return ret; } -static int __devinit ndfc_probe(struct platform_device *ofdev) +static int ndfc_probe(struct platform_device *ofdev) { struct ndfc_controller *ndfc; const __be32 *reg; @@ -256,7 +256,7 @@ static int __devinit ndfc_probe(struct platform_device *ofdev) return 0; } -static int __devexit ndfc_remove(struct platform_device *ofdev) +static int ndfc_remove(struct platform_device *ofdev) { struct ndfc_controller *ndfc = dev_get_drvdata(&ofdev->dev); @@ -279,7 +279,7 @@ static struct platform_driver ndfc_driver = { .of_match_table = ndfc_match, }, .probe = ndfc_probe, - .remove = __devexit_p(ndfc_remove), + .remove = ndfc_remove, }; module_platform_driver(ndfc_driver); diff --git a/drivers/mtd/nand/nomadik_nand.c b/drivers/mtd/nand/nomadik_nand.c deleted file mode 100644 index 9ee0c4edfacf..000000000000 --- a/drivers/mtd/nand/nomadik_nand.c +++ /dev/null @@ -1,235 +0,0 @@ -/* - * drivers/mtd/nand/nomadik_nand.c - * - * Overview: - * Driver for on-board NAND flash on Nomadik Platforms - * - * Copyright © 2007 STMicroelectronics Pvt. Ltd. - * Author: Sachin Verma <sachin.verma@st.com> - * - * Copyright © 2009 Alessandro Rubini - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#include <linux/init.h> -#include <linux/module.h> -#include <linux/types.h> -#include <linux/mtd/mtd.h> -#include <linux/mtd/nand.h> -#include <linux/mtd/nand_ecc.h> -#include <linux/platform_device.h> -#include <linux/mtd/partitions.h> -#include <linux/io.h> -#include <linux/slab.h> -#include <linux/platform_data/mtd-nomadik-nand.h> -#include <mach/fsmc.h> - -#include <mtd/mtd-abi.h> - -struct nomadik_nand_host { - struct mtd_info mtd; - struct nand_chip nand; - void __iomem *data_va; - void __iomem *cmd_va; - void __iomem *addr_va; - struct nand_bbt_descr *bbt_desc; -}; - -static struct nand_ecclayout nomadik_ecc_layout = { - .eccbytes = 3 * 4, - .eccpos = { /* each subpage has 16 bytes: pos 2,3,4 hosts ECC */ - 0x02, 0x03, 0x04, - 0x12, 0x13, 0x14, - 0x22, 0x23, 0x24, - 0x32, 0x33, 0x34}, - /* let's keep bytes 5,6,7 for us, just in case we change ECC algo */ - .oobfree = { {0x08, 0x08}, {0x18, 0x08}, {0x28, 0x08}, {0x38, 0x08} }, -}; - -static void nomadik_ecc_control(struct mtd_info *mtd, int mode) -{ - /* No need to enable hw ecc, it's on by default */ -} - -static void nomadik_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) -{ - struct nand_chip *nand = mtd->priv; - struct nomadik_nand_host *host = nand->priv; - - if (cmd == NAND_CMD_NONE) - return; - - if (ctrl & NAND_CLE) - writeb(cmd, host->cmd_va); - else - writeb(cmd, host->addr_va); -} - -static int nomadik_nand_probe(struct platform_device *pdev) -{ - struct nomadik_nand_platform_data *pdata = pdev->dev.platform_data; - struct nomadik_nand_host *host; - struct mtd_info *mtd; - struct nand_chip *nand; - struct resource *res; - int ret = 0; - - /* Allocate memory for the device structure (and zero it) */ - host = kzalloc(sizeof(struct nomadik_nand_host), GFP_KERNEL); - if (!host) { - dev_err(&pdev->dev, "Failed to allocate device structure.\n"); - return -ENOMEM; - } - - /* Call the client's init function, if any */ - if (pdata->init) - ret = pdata->init(); - if (ret < 0) { - dev_err(&pdev->dev, "Init function failed\n"); - goto err; - } - - /* ioremap three regions */ - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nand_addr"); - if (!res) { - ret = -EIO; - goto err_unmap; - } - host->addr_va = ioremap(res->start, resource_size(res)); - - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nand_data"); - if (!res) { - ret = -EIO; - goto err_unmap; - } - host->data_va = ioremap(res->start, resource_size(res)); - - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nand_cmd"); - if (!res) { - ret = -EIO; - goto err_unmap; - } - host->cmd_va = ioremap(res->start, resource_size(res)); - - if (!host->addr_va || !host->data_va || !host->cmd_va) { - ret = -ENOMEM; - goto err_unmap; - } - - /* Link all private pointers */ - mtd = &host->mtd; - nand = &host->nand; - mtd->priv = nand; - nand->priv = host; - - host->mtd.owner = THIS_MODULE; - nand->IO_ADDR_R = host->data_va; - nand->IO_ADDR_W = host->data_va; - nand->cmd_ctrl = nomadik_cmd_ctrl; - - /* - * This stanza declares ECC_HW but uses soft routines. It's because - * HW claims to make the calculation but not the correction. However, - * I haven't managed to get the desired data out of it until now. - */ - nand->ecc.mode = NAND_ECC_SOFT; - nand->ecc.layout = &nomadik_ecc_layout; - nand->ecc.hwctl = nomadik_ecc_control; - nand->ecc.size = 512; - nand->ecc.bytes = 3; - - nand->options = pdata->options; - - /* - * Scan to find existence of the device - */ - if (nand_scan(&host->mtd, 1)) { - ret = -ENXIO; - goto err_unmap; - } - - mtd_device_register(&host->mtd, pdata->parts, pdata->nparts); - - platform_set_drvdata(pdev, host); - return 0; - - err_unmap: - if (host->cmd_va) - iounmap(host->cmd_va); - if (host->data_va) - iounmap(host->data_va); - if (host->addr_va) - iounmap(host->addr_va); - err: - kfree(host); - return ret; -} - -/* - * Clean up routine - */ -static int nomadik_nand_remove(struct platform_device *pdev) -{ - struct nomadik_nand_host *host = platform_get_drvdata(pdev); - struct nomadik_nand_platform_data *pdata = pdev->dev.platform_data; - - if (pdata->exit) - pdata->exit(); - - if (host) { - nand_release(&host->mtd); - iounmap(host->cmd_va); - iounmap(host->data_va); - iounmap(host->addr_va); - kfree(host); - } - return 0; -} - -static int nomadik_nand_suspend(struct device *dev) -{ - struct nomadik_nand_host *host = dev_get_drvdata(dev); - int ret = 0; - if (host) - ret = mtd_suspend(&host->mtd); - return ret; -} - -static int nomadik_nand_resume(struct device *dev) -{ - struct nomadik_nand_host *host = dev_get_drvdata(dev); - if (host) - mtd_resume(&host->mtd); - return 0; -} - -static const struct dev_pm_ops nomadik_nand_pm_ops = { - .suspend = nomadik_nand_suspend, - .resume = nomadik_nand_resume, -}; - -static struct platform_driver nomadik_nand_driver = { - .probe = nomadik_nand_probe, - .remove = nomadik_nand_remove, - .driver = { - .owner = THIS_MODULE, - .name = "nomadik_nand", - .pm = &nomadik_nand_pm_ops, - }, -}; - -module_platform_driver(nomadik_nand_driver); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("ST Microelectronics (sachin.verma@st.com)"); -MODULE_DESCRIPTION("NAND driver for Nomadik Platform"); diff --git a/drivers/mtd/nand/nuc900_nand.c b/drivers/mtd/nand/nuc900_nand.c index 94dc46bc118c..a6191198d259 100644 --- a/drivers/mtd/nand/nuc900_nand.c +++ b/drivers/mtd/nand/nuc900_nand.c @@ -246,7 +246,7 @@ static void nuc900_nand_enable(struct nuc900_nand *nand) spin_unlock(&nand->lock); } -static int __devinit nuc900_nand_probe(struct platform_device *pdev) +static int nuc900_nand_probe(struct platform_device *pdev) { struct nuc900_nand *nuc900_nand; struct nand_chip *chip; @@ -317,7 +317,7 @@ fail1: kfree(nuc900_nand); return retval; } -static int __devexit nuc900_nand_remove(struct platform_device *pdev) +static int nuc900_nand_remove(struct platform_device *pdev) { struct nuc900_nand *nuc900_nand = platform_get_drvdata(pdev); struct resource *res; @@ -340,7 +340,7 @@ static int __devexit nuc900_nand_remove(struct platform_device *pdev) static struct platform_driver nuc900_nand_driver = { .probe = nuc900_nand_probe, - .remove = __devexit_p(nuc900_nand_remove), + .remove = nuc900_nand_remove, .driver = { .name = "nuc900-fmi", .owner = THIS_MODULE, diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index 5b3138620646..0002d5e94f0d 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -27,8 +27,6 @@ #include <linux/bch.h> #endif -#include <plat/dma.h> -#include <plat/gpmc.h> #include <linux/platform_data/mtd-nand-omap2.h> #define DRIVER_NAME "omap2-nand" @@ -106,10 +104,18 @@ #define CS_MASK 0x7 #define ENABLE_PREFETCH (0x1 << 7) #define DMA_MPU_MODE_SHIFT 2 +#define ECCSIZE0_SHIFT 12 #define ECCSIZE1_SHIFT 22 #define ECC1RESULTSIZE 0x1 #define ECCCLEAR 0x100 #define ECC1 0x1 +#define PREFETCH_FIFOTHRESHOLD_MAX 0x40 +#define PREFETCH_FIFOTHRESHOLD(val) ((val) << 8) +#define PREFETCH_STATUS_COUNT(val) (val & 0x00003fff) +#define PREFETCH_STATUS_FIFO_CNT(val) ((val >> 24) & 0x7F) +#define STATUS_BUFF_EMPTY 0x00000001 + +#define OMAP24XX_DMA_GPMC 4 /* oob info generated runtime depending on ecc algorithm and layout selected */ static struct nand_ecclayout omap_oobinfo; @@ -269,7 +275,7 @@ static void omap_write_buf8(struct mtd_info *mtd, const u_char *buf, int len) /* wait until buffer is available for write */ do { status = readl(info->reg.gpmc_status) & - GPMC_STATUS_BUFF_EMPTY; + STATUS_BUFF_EMPTY; } while (!status); } } @@ -307,7 +313,7 @@ static void omap_write_buf16(struct mtd_info *mtd, const u_char * buf, int len) /* wait until buffer is available for write */ do { status = readl(info->reg.gpmc_status) & - GPMC_STATUS_BUFF_EMPTY; + STATUS_BUFF_EMPTY; } while (!status); } } @@ -348,7 +354,7 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len) } else { do { r_count = readl(info->reg.gpmc_prefetch_status); - r_count = GPMC_PREFETCH_STATUS_FIFO_CNT(r_count); + r_count = PREFETCH_STATUS_FIFO_CNT(r_count); r_count = r_count >> 2; ioread32_rep(info->nand.IO_ADDR_R, p, r_count); p += r_count; @@ -395,7 +401,7 @@ static void omap_write_buf_pref(struct mtd_info *mtd, } else { while (len) { w_count = readl(info->reg.gpmc_prefetch_status); - w_count = GPMC_PREFETCH_STATUS_FIFO_CNT(w_count); + w_count = PREFETCH_STATUS_FIFO_CNT(w_count); w_count = w_count >> 1; for (i = 0; (i < w_count) && len; i++, len -= 2) iowrite16(*p++, info->nand.IO_ADDR_W); @@ -407,7 +413,7 @@ static void omap_write_buf_pref(struct mtd_info *mtd, do { cpu_relax(); val = readl(info->reg.gpmc_prefetch_status); - val = GPMC_PREFETCH_STATUS_COUNT(val); + val = PREFETCH_STATUS_COUNT(val); } while (val && (tim++ < limit)); /* disable and stop the PFPW engine */ @@ -493,7 +499,7 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr, do { cpu_relax(); val = readl(info->reg.gpmc_prefetch_status); - val = GPMC_PREFETCH_STATUS_COUNT(val); + val = PREFETCH_STATUS_COUNT(val); } while (val && (tim++ < limit)); /* disable and stop the PFPW engine */ @@ -556,7 +562,7 @@ static irqreturn_t omap_nand_irq(int this_irq, void *dev) u32 bytes; bytes = readl(info->reg.gpmc_prefetch_status); - bytes = GPMC_PREFETCH_STATUS_FIFO_CNT(bytes); + bytes = PREFETCH_STATUS_FIFO_CNT(bytes); bytes = bytes & 0xFFFC; /* io in multiple of 4 bytes */ if (info->iomode == OMAP_NAND_IO_WRITE) { /* checks for write io */ if (this_irq == info->gpmc_irq_count) @@ -682,7 +688,7 @@ static void omap_write_buf_irq_pref(struct mtd_info *mtd, limit = (loops_per_jiffy * msecs_to_jiffies(OMAP_NAND_TIMEOUT_MS)); do { val = readl(info->reg.gpmc_prefetch_status); - val = GPMC_PREFETCH_STATUS_COUNT(val); + val = PREFETCH_STATUS_COUNT(val); cpu_relax(); } while (val && (tim++ < limit)); @@ -996,7 +1002,7 @@ static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip) cond_resched(); } - status = gpmc_nand_read(info->gpmc_cs, GPMC_NAND_DATA); + status = readb(info->reg.gpmc_nand_data); return status; } @@ -1029,19 +1035,45 @@ static int omap_dev_ready(struct mtd_info *mtd) static void omap3_enable_hwecc_bch(struct mtd_info *mtd, int mode) { int nerrors; - unsigned int dev_width; + unsigned int dev_width, nsectors; struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, mtd); struct nand_chip *chip = mtd->priv; + u32 val; nerrors = (info->nand.ecc.bytes == 13) ? 8 : 4; dev_width = (chip->options & NAND_BUSWIDTH_16) ? 1 : 0; + nsectors = 1; /* * Program GPMC to perform correction on one 512-byte sector at a time. * Using 4 sectors at a time (i.e. ecc.size = 2048) is also possible and * gives a slight (5%) performance gain (but requires additional code). */ - (void)gpmc_enable_hwecc_bch(info->gpmc_cs, mode, dev_width, 1, nerrors); + + writel(ECC1, info->reg.gpmc_ecc_control); + + /* + * When using BCH, sector size is hardcoded to 512 bytes. + * Here we are using wrapping mode 6 both for reading and writing, with: + * size0 = 0 (no additional protected byte in spare area) + * size1 = 32 (skip 32 nibbles = 16 bytes per sector in spare area) + */ + val = (32 << ECCSIZE1_SHIFT) | (0 << ECCSIZE0_SHIFT); + writel(val, info->reg.gpmc_ecc_size_config); + + /* BCH configuration */ + val = ((1 << 16) | /* enable BCH */ + (((nerrors == 8) ? 1 : 0) << 12) | /* 8 or 4 bits */ + (0x06 << 8) | /* wrap mode = 6 */ + (dev_width << 7) | /* bus width */ + (((nsectors-1) & 0x7) << 4) | /* number of sectors */ + (info->gpmc_cs << 1) | /* ECC CS */ + (0x1)); /* enable ECC */ + + writel(val, info->reg.gpmc_ecc_config); + + /* clear ecc and enable bits */ + writel(ECCCLEAR | ECC1, info->reg.gpmc_ecc_control); } /** @@ -1055,7 +1087,32 @@ static int omap3_calculate_ecc_bch4(struct mtd_info *mtd, const u_char *dat, { struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, mtd); - return gpmc_calculate_ecc_bch4(info->gpmc_cs, dat, ecc_code); + unsigned long nsectors, val1, val2; + int i; + + nsectors = ((readl(info->reg.gpmc_ecc_config) >> 4) & 0x7) + 1; + + for (i = 0; i < nsectors; i++) { + + /* Read hw-computed remainder */ + val1 = readl(info->reg.gpmc_bch_result0[i]); + val2 = readl(info->reg.gpmc_bch_result1[i]); + + /* + * Add constant polynomial to remainder, in order to get an ecc + * sequence of 0xFFs for a buffer filled with 0xFFs; and + * left-justify the resulting polynomial. + */ + *ecc_code++ = 0x28 ^ ((val2 >> 12) & 0xFF); + *ecc_code++ = 0x13 ^ ((val2 >> 4) & 0xFF); + *ecc_code++ = 0xcc ^ (((val2 & 0xF) << 4)|((val1 >> 28) & 0xF)); + *ecc_code++ = 0x39 ^ ((val1 >> 20) & 0xFF); + *ecc_code++ = 0x96 ^ ((val1 >> 12) & 0xFF); + *ecc_code++ = 0xac ^ ((val1 >> 4) & 0xFF); + *ecc_code++ = 0x7f ^ ((val1 & 0xF) << 4); + } + + return 0; } /** @@ -1069,7 +1126,39 @@ static int omap3_calculate_ecc_bch8(struct mtd_info *mtd, const u_char *dat, { struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, mtd); - return gpmc_calculate_ecc_bch8(info->gpmc_cs, dat, ecc_code); + unsigned long nsectors, val1, val2, val3, val4; + int i; + + nsectors = ((readl(info->reg.gpmc_ecc_config) >> 4) & 0x7) + 1; + + for (i = 0; i < nsectors; i++) { + + /* Read hw-computed remainder */ + val1 = readl(info->reg.gpmc_bch_result0[i]); + val2 = readl(info->reg.gpmc_bch_result1[i]); + val3 = readl(info->reg.gpmc_bch_result2[i]); + val4 = readl(info->reg.gpmc_bch_result3[i]); + + /* + * Add constant polynomial to remainder, in order to get an ecc + * sequence of 0xFFs for a buffer filled with 0xFFs. + */ + *ecc_code++ = 0xef ^ (val4 & 0xFF); + *ecc_code++ = 0x51 ^ ((val3 >> 24) & 0xFF); + *ecc_code++ = 0x2e ^ ((val3 >> 16) & 0xFF); + *ecc_code++ = 0x09 ^ ((val3 >> 8) & 0xFF); + *ecc_code++ = 0xed ^ (val3 & 0xFF); + *ecc_code++ = 0x93 ^ ((val2 >> 24) & 0xFF); + *ecc_code++ = 0x9a ^ ((val2 >> 16) & 0xFF); + *ecc_code++ = 0xc2 ^ ((val2 >> 8) & 0xFF); + *ecc_code++ = 0x97 ^ (val2 & 0xFF); + *ecc_code++ = 0x79 ^ ((val1 >> 24) & 0xFF); + *ecc_code++ = 0xe5 ^ ((val1 >> 16) & 0xFF); + *ecc_code++ = 0x24 ^ ((val1 >> 8) & 0xFF); + *ecc_code++ = 0xb5 ^ (val1 & 0xFF); + } + + return 0; } /** @@ -1125,7 +1214,7 @@ static void omap3_free_bch(struct mtd_info *mtd) */ static int omap3_init_bch(struct mtd_info *mtd, int ecc_opt) { - int ret, max_errors; + int max_errors; struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, mtd); #ifdef CONFIG_MTD_NAND_OMAP_BCH8 @@ -1142,11 +1231,6 @@ static int omap3_init_bch(struct mtd_info *mtd, int ecc_opt) goto fail; } - /* initialize GPMC BCH engine */ - ret = gpmc_init_hwecc_bch(info->gpmc_cs, 1, max_errors); - if (ret) - goto fail; - /* software bch library is only used to detect and locate errors */ info->bch = init_bch(13, max_errors, 0x201b /* hw polynomial */); if (!info->bch) @@ -1239,7 +1323,7 @@ static void omap3_free_bch(struct mtd_info *mtd) } #endif /* CONFIG_MTD_NAND_OMAP_BCH */ -static int __devinit omap_nand_probe(struct platform_device *pdev) +static int omap_nand_probe(struct platform_device *pdev) { struct omap_nand_info *info; struct omap_nand_platform_data *pdata; @@ -1513,7 +1597,7 @@ static int omap_nand_remove(struct platform_device *pdev) /* Release NAND device, its internal structures and partitions */ nand_release(&info->mtd); iounmap(info->nand.IO_ADDR_R); - release_mem_region(info->phys_base, NAND_IO_SIZE); + release_mem_region(info->phys_base, info->mem_size); kfree(info); return 0; } diff --git a/drivers/mtd/nand/orion_nand.c b/drivers/mtd/nand/orion_nand.c index aefaf8cd31ef..cd72b9299f6b 100644 --- a/drivers/mtd/nand/orion_nand.c +++ b/drivers/mtd/nand/orion_nand.c @@ -194,7 +194,7 @@ no_res: return ret; } -static int __devexit orion_nand_remove(struct platform_device *pdev) +static int orion_nand_remove(struct platform_device *pdev) { struct mtd_info *mtd = platform_get_drvdata(pdev); struct nand_chip *nc = mtd->priv; @@ -223,7 +223,7 @@ static struct of_device_id orion_nand_of_match_table[] = { #endif static struct platform_driver orion_nand_driver = { - .remove = __devexit_p(orion_nand_remove), + .remove = orion_nand_remove, .driver = { .name = "orion_nand", .owner = THIS_MODULE, diff --git a/drivers/mtd/nand/pasemi_nand.c b/drivers/mtd/nand/pasemi_nand.c index 1440e51cedcc..5a67082c07ee 100644 --- a/drivers/mtd/nand/pasemi_nand.c +++ b/drivers/mtd/nand/pasemi_nand.c @@ -89,7 +89,7 @@ int pasemi_device_ready(struct mtd_info *mtd) return !!(inl(lpcctl) & LBICTRL_LPCCTL_NR); } -static int __devinit pasemi_nand_probe(struct platform_device *ofdev) +static int pasemi_nand_probe(struct platform_device *ofdev) { struct pci_dev *pdev; struct device_node *np = ofdev->dev.of_node; @@ -184,7 +184,7 @@ static int __devinit pasemi_nand_probe(struct platform_device *ofdev) return err; } -static int __devexit pasemi_nand_remove(struct platform_device *ofdev) +static int pasemi_nand_remove(struct platform_device *ofdev) { struct nand_chip *chip; diff --git a/drivers/mtd/nand/plat_nand.c b/drivers/mtd/nand/plat_nand.c index a47ee68a0cfa..c004566a9ad2 100644 --- a/drivers/mtd/nand/plat_nand.c +++ b/drivers/mtd/nand/plat_nand.c @@ -28,7 +28,7 @@ static const char *part_probe_types[] = { "cmdlinepart", NULL }; /* * Probe for the NAND device. */ -static int __devinit plat_nand_probe(struct platform_device *pdev) +static int plat_nand_probe(struct platform_device *pdev) { struct platform_nand_data *pdata = pdev->dev.platform_data; struct mtd_part_parser_data ppdata; @@ -134,7 +134,7 @@ out_free: /* * Remove a NAND device. */ -static int __devexit plat_nand_remove(struct platform_device *pdev) +static int plat_nand_remove(struct platform_device *pdev) { struct plat_nand_data *data = platform_get_drvdata(pdev); struct platform_nand_data *pdata = pdev->dev.platform_data; @@ -160,7 +160,7 @@ MODULE_DEVICE_TABLE(of, plat_nand_match); static struct platform_driver plat_nand_driver = { .probe = plat_nand_probe, - .remove = __devexit_p(plat_nand_remove), + .remove = plat_nand_remove, .driver = { .name = "gen_nand", .owner = THIS_MODULE, diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c index 295e4bedad96..df954b4dcba2 100644 --- a/drivers/mtd/nand/s3c2410.c +++ b/drivers/mtd/nand/s3c2410.c @@ -730,11 +730,14 @@ static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info, struct s3c2410_nand_mtd *mtd, struct s3c2410_nand_set *set) { - if (set) + if (set) { mtd->mtd.name = set->name; - return mtd_device_parse_register(&mtd->mtd, NULL, NULL, + return mtd_device_parse_register(&mtd->mtd, NULL, NULL, set->partitions, set->nr_partitions); + } + + return -ENODEV; } /** @@ -879,7 +882,7 @@ static void s3c2410_nand_update_chip(struct s3c2410_nand_info *info, if (chip->ecc.mode != NAND_ECC_HW) return; - /* change the behaviour depending on wether we are using + /* change the behaviour depending on whether we are using * the large or small page nand device */ if (chip->page_shift > 10) { diff --git a/drivers/mtd/nand/sh_flctl.c b/drivers/mtd/nand/sh_flctl.c index 4fbfe96e37a1..57b3971c9c0a 100644 --- a/drivers/mtd/nand/sh_flctl.c +++ b/drivers/mtd/nand/sh_flctl.c @@ -23,11 +23,18 @@ #include <linux/module.h> #include <linux/kernel.h> +#include <linux/completion.h> #include <linux/delay.h> +#include <linux/dmaengine.h> +#include <linux/dma-mapping.h> #include <linux/interrupt.h> #include <linux/io.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/of_mtd.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> +#include <linux/sh_dma.h> #include <linux/slab.h> #include <linux/string.h> @@ -106,6 +113,84 @@ static void wait_completion(struct sh_flctl *flctl) writeb(0x0, FLTRCR(flctl)); } +static void flctl_dma_complete(void *param) +{ + struct sh_flctl *flctl = param; + + complete(&flctl->dma_complete); +} + +static void flctl_release_dma(struct sh_flctl *flctl) +{ + if (flctl->chan_fifo0_rx) { + dma_release_channel(flctl->chan_fifo0_rx); + flctl->chan_fifo0_rx = NULL; + } + if (flctl->chan_fifo0_tx) { + dma_release_channel(flctl->chan_fifo0_tx); + flctl->chan_fifo0_tx = NULL; + } +} + +static void flctl_setup_dma(struct sh_flctl *flctl) +{ + dma_cap_mask_t mask; + struct dma_slave_config cfg; + struct platform_device *pdev = flctl->pdev; + struct sh_flctl_platform_data *pdata = pdev->dev.platform_data; + int ret; + + if (!pdata) + return; + + if (pdata->slave_id_fifo0_tx <= 0 || pdata->slave_id_fifo0_rx <= 0) + return; + + /* We can only either use DMA for both Tx and Rx or not use it at all */ + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + + flctl->chan_fifo0_tx = dma_request_channel(mask, shdma_chan_filter, + (void *)pdata->slave_id_fifo0_tx); + dev_dbg(&pdev->dev, "%s: TX: got channel %p\n", __func__, + flctl->chan_fifo0_tx); + + if (!flctl->chan_fifo0_tx) + return; + + memset(&cfg, 0, sizeof(cfg)); + cfg.slave_id = pdata->slave_id_fifo0_tx; + cfg.direction = DMA_MEM_TO_DEV; + cfg.dst_addr = (dma_addr_t)FLDTFIFO(flctl); + cfg.src_addr = 0; + ret = dmaengine_slave_config(flctl->chan_fifo0_tx, &cfg); + if (ret < 0) + goto err; + + flctl->chan_fifo0_rx = dma_request_channel(mask, shdma_chan_filter, + (void *)pdata->slave_id_fifo0_rx); + dev_dbg(&pdev->dev, "%s: RX: got channel %p\n", __func__, + flctl->chan_fifo0_rx); + + if (!flctl->chan_fifo0_rx) + goto err; + + cfg.slave_id = pdata->slave_id_fifo0_rx; + cfg.direction = DMA_DEV_TO_MEM; + cfg.dst_addr = 0; + cfg.src_addr = (dma_addr_t)FLDTFIFO(flctl); + ret = dmaengine_slave_config(flctl->chan_fifo0_rx, &cfg); + if (ret < 0) + goto err; + + init_completion(&flctl->dma_complete); + + return; + +err: + flctl_release_dma(flctl); +} + static void set_addr(struct mtd_info *mtd, int column, int page_addr) { struct sh_flctl *flctl = mtd_to_flctl(mtd); @@ -225,7 +310,7 @@ static enum flctl_ecc_res_t wait_recfifo_ready for (i = 0; i < 3; i++) { uint8_t org; - int index; + unsigned int index; data = readl(ecc_reg[i]); @@ -261,6 +346,70 @@ static void wait_wecfifo_ready(struct sh_flctl *flctl) timeout_error(flctl, __func__); } +static int flctl_dma_fifo0_transfer(struct sh_flctl *flctl, unsigned long *buf, + int len, enum dma_data_direction dir) +{ + struct dma_async_tx_descriptor *desc = NULL; + struct dma_chan *chan; + enum dma_transfer_direction tr_dir; + dma_addr_t dma_addr; + dma_cookie_t cookie = -EINVAL; + uint32_t reg; + int ret; + + if (dir == DMA_FROM_DEVICE) { + chan = flctl->chan_fifo0_rx; + tr_dir = DMA_DEV_TO_MEM; + } else { + chan = flctl->chan_fifo0_tx; + tr_dir = DMA_MEM_TO_DEV; + } + + dma_addr = dma_map_single(chan->device->dev, buf, len, dir); + + if (dma_addr) + desc = dmaengine_prep_slave_single(chan, dma_addr, len, + tr_dir, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + + if (desc) { + reg = readl(FLINTDMACR(flctl)); + reg |= DREQ0EN; + writel(reg, FLINTDMACR(flctl)); + + desc->callback = flctl_dma_complete; + desc->callback_param = flctl; + cookie = dmaengine_submit(desc); + + dma_async_issue_pending(chan); + } else { + /* DMA failed, fall back to PIO */ + flctl_release_dma(flctl); + dev_warn(&flctl->pdev->dev, + "DMA failed, falling back to PIO\n"); + ret = -EIO; + goto out; + } + + ret = + wait_for_completion_timeout(&flctl->dma_complete, + msecs_to_jiffies(3000)); + + if (ret <= 0) { + chan->device->device_control(chan, DMA_TERMINATE_ALL, 0); + dev_err(&flctl->pdev->dev, "wait_for_completion_timeout\n"); + } + +out: + reg = readl(FLINTDMACR(flctl)); + reg &= ~DREQ0EN; + writel(reg, FLINTDMACR(flctl)); + + dma_unmap_single(chan->device->dev, dma_addr, len, dir); + + /* ret > 0 is success */ + return ret; +} + static void read_datareg(struct sh_flctl *flctl, int offset) { unsigned long data; @@ -279,11 +428,20 @@ static void read_fiforeg(struct sh_flctl *flctl, int rlen, int offset) len_4align = (rlen + 3) / 4; + /* initiate DMA transfer */ + if (flctl->chan_fifo0_rx && rlen >= 32 && + flctl_dma_fifo0_transfer(flctl, buf, rlen, DMA_DEV_TO_MEM) > 0) + goto convert; /* DMA success */ + + /* do polling transfer */ for (i = 0; i < len_4align; i++) { wait_rfifo_ready(flctl); buf[i] = readl(FLDTFIFO(flctl)); - buf[i] = be32_to_cpu(buf[i]); } + +convert: + for (i = 0; i < len_4align; i++) + buf[i] = be32_to_cpu(buf[i]); } static enum flctl_ecc_res_t read_ecfiforeg @@ -305,28 +463,39 @@ static enum flctl_ecc_res_t read_ecfiforeg return res; } -static void write_fiforeg(struct sh_flctl *flctl, int rlen, int offset) +static void write_fiforeg(struct sh_flctl *flctl, int rlen, + unsigned int offset) { int i, len_4align; - unsigned long *data = (unsigned long *)&flctl->done_buff[offset]; - void *fifo_addr = (void *)FLDTFIFO(flctl); + unsigned long *buf = (unsigned long *)&flctl->done_buff[offset]; len_4align = (rlen + 3) / 4; for (i = 0; i < len_4align; i++) { wait_wfifo_ready(flctl); - writel(cpu_to_be32(data[i]), fifo_addr); + writel(cpu_to_be32(buf[i]), FLDTFIFO(flctl)); } } -static void write_ec_fiforeg(struct sh_flctl *flctl, int rlen, int offset) +static void write_ec_fiforeg(struct sh_flctl *flctl, int rlen, + unsigned int offset) { int i, len_4align; - unsigned long *data = (unsigned long *)&flctl->done_buff[offset]; + unsigned long *buf = (unsigned long *)&flctl->done_buff[offset]; len_4align = (rlen + 3) / 4; + + for (i = 0; i < len_4align; i++) + buf[i] = cpu_to_be32(buf[i]); + + /* initiate DMA transfer */ + if (flctl->chan_fifo0_tx && rlen >= 32 && + flctl_dma_fifo0_transfer(flctl, buf, rlen, DMA_MEM_TO_DEV) > 0) + return; /* DMA success */ + + /* do polling transfer */ for (i = 0; i < len_4align; i++) { wait_wecfifo_ready(flctl); - writel(cpu_to_be32(data[i]), FLECFIFO(flctl)); + writel(buf[i], FLECFIFO(flctl)); } } @@ -727,7 +896,9 @@ static void flctl_select_chip(struct mtd_info *mtd, int chipnr) if (!flctl->qos_request) { ret = dev_pm_qos_add_request(&flctl->pdev->dev, - &flctl->pm_qos, 100); + &flctl->pm_qos, + DEV_PM_QOS_LATENCY, + 100); if (ret < 0) dev_err(&flctl->pdev->dev, "PM QoS request failed: %d\n", ret); @@ -748,41 +919,35 @@ static void flctl_select_chip(struct mtd_info *mtd, int chipnr) static void flctl_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) { struct sh_flctl *flctl = mtd_to_flctl(mtd); - int index = flctl->index; - memcpy(&flctl->done_buff[index], buf, len); + memcpy(&flctl->done_buff[flctl->index], buf, len); flctl->index += len; } static uint8_t flctl_read_byte(struct mtd_info *mtd) { struct sh_flctl *flctl = mtd_to_flctl(mtd); - int index = flctl->index; uint8_t data; - data = flctl->done_buff[index]; + data = flctl->done_buff[flctl->index]; flctl->index++; return data; } static uint16_t flctl_read_word(struct mtd_info *mtd) { - struct sh_flctl *flctl = mtd_to_flctl(mtd); - int index = flctl->index; - uint16_t data; - uint16_t *buf = (uint16_t *)&flctl->done_buff[index]; + struct sh_flctl *flctl = mtd_to_flctl(mtd); + uint16_t *buf = (uint16_t *)&flctl->done_buff[flctl->index]; - data = *buf; - flctl->index += 2; - return data; + flctl->index += 2; + return *buf; } static void flctl_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) { struct sh_flctl *flctl = mtd_to_flctl(mtd); - int index = flctl->index; - memcpy(buf, &flctl->done_buff[index], len); + memcpy(buf, &flctl->done_buff[flctl->index], len); flctl->index += len; } @@ -856,7 +1021,74 @@ static irqreturn_t flctl_handle_flste(int irq, void *dev_id) return IRQ_HANDLED; } -static int __devinit flctl_probe(struct platform_device *pdev) +#ifdef CONFIG_OF +struct flctl_soc_config { + unsigned long flcmncr_val; + unsigned has_hwecc:1; + unsigned use_holden:1; +}; + +static struct flctl_soc_config flctl_sh7372_config = { + .flcmncr_val = CLK_16B_12L_4H | TYPESEL_SET | SHBUSSEL, + .has_hwecc = 1, + .use_holden = 1, +}; + +static const struct of_device_id of_flctl_match[] = { + { .compatible = "renesas,shmobile-flctl-sh7372", + .data = &flctl_sh7372_config }, + {}, +}; +MODULE_DEVICE_TABLE(of, of_flctl_match); + +static struct sh_flctl_platform_data *flctl_parse_dt(struct device *dev) +{ + const struct of_device_id *match; + struct flctl_soc_config *config; + struct sh_flctl_platform_data *pdata; + struct device_node *dn = dev->of_node; + int ret; + + match = of_match_device(of_flctl_match, dev); + if (match) + config = (struct flctl_soc_config *)match->data; + else { + dev_err(dev, "%s: no OF configuration attached\n", __func__); + return NULL; + } + + pdata = devm_kzalloc(dev, sizeof(struct sh_flctl_platform_data), + GFP_KERNEL); + if (!pdata) { + dev_err(dev, "%s: failed to allocate config data\n", __func__); + return NULL; + } + + /* set SoC specific options */ + pdata->flcmncr_val = config->flcmncr_val; + pdata->has_hwecc = config->has_hwecc; + pdata->use_holden = config->use_holden; + + /* parse user defined options */ + ret = of_get_nand_bus_width(dn); + if (ret == 16) + pdata->flcmncr_val |= SEL_16BIT; + else if (ret != 8) { + dev_err(dev, "%s: invalid bus width\n", __func__); + return NULL; + } + + return pdata; +} +#else /* CONFIG_OF */ +#define of_flctl_match NULL +static struct sh_flctl_platform_data *flctl_parse_dt(struct device *dev) +{ + return NULL; +} +#endif /* CONFIG_OF */ + +static int flctl_probe(struct platform_device *pdev) { struct resource *res; struct sh_flctl *flctl; @@ -865,12 +1097,7 @@ static int __devinit flctl_probe(struct platform_device *pdev) struct sh_flctl_platform_data *pdata; int ret = -ENXIO; int irq; - - pdata = pdev->dev.platform_data; - if (pdata == NULL) { - dev_err(&pdev->dev, "no platform data defined\n"); - return -EINVAL; - } + struct mtd_part_parser_data ppdata = {}; flctl = kzalloc(sizeof(struct sh_flctl), GFP_KERNEL); if (!flctl) { @@ -902,6 +1129,17 @@ static int __devinit flctl_probe(struct platform_device *pdev) goto err_flste; } + if (pdev->dev.of_node) + pdata = flctl_parse_dt(&pdev->dev); + else + pdata = pdev->dev.platform_data; + + if (!pdata) { + dev_err(&pdev->dev, "no setup data defined\n"); + ret = -EINVAL; + goto err_pdata; + } + platform_set_drvdata(pdev, flctl); flctl_mtd = &flctl->mtd; nand = &flctl->chip; @@ -930,6 +1168,8 @@ static int __devinit flctl_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); pm_runtime_resume(&pdev->dev); + flctl_setup_dma(flctl); + ret = nand_scan_ident(flctl_mtd, 1, NULL); if (ret) goto err_chip; @@ -942,12 +1182,16 @@ static int __devinit flctl_probe(struct platform_device *pdev) if (ret) goto err_chip; - mtd_device_register(flctl_mtd, pdata->parts, pdata->nr_parts); + ppdata.of_node = pdev->dev.of_node; + ret = mtd_device_parse_register(flctl_mtd, NULL, &ppdata, pdata->parts, + pdata->nr_parts); return 0; err_chip: + flctl_release_dma(flctl); pm_runtime_disable(&pdev->dev); +err_pdata: free_irq(irq, flctl); err_flste: iounmap(flctl->reg); @@ -956,10 +1200,11 @@ err_iomap: return ret; } -static int __devexit flctl_remove(struct platform_device *pdev) +static int flctl_remove(struct platform_device *pdev) { struct sh_flctl *flctl = platform_get_drvdata(pdev); + flctl_release_dma(flctl); nand_release(&flctl->mtd); pm_runtime_disable(&pdev->dev); free_irq(platform_get_irq(pdev, 0), flctl); @@ -974,6 +1219,7 @@ static struct platform_driver flctl_driver = { .driver = { .name = "sh_flctl", .owner = THIS_MODULE, + .of_match_table = of_flctl_match, }, }; diff --git a/drivers/mtd/nand/sharpsl.c b/drivers/mtd/nand/sharpsl.c index 3421e3762a5a..127bc4271821 100644 --- a/drivers/mtd/nand/sharpsl.c +++ b/drivers/mtd/nand/sharpsl.c @@ -106,7 +106,7 @@ static int sharpsl_nand_calculate_ecc(struct mtd_info *mtd, const u_char * dat, /* * Main initialization routine */ -static int __devinit sharpsl_nand_probe(struct platform_device *pdev) +static int sharpsl_nand_probe(struct platform_device *pdev) { struct nand_chip *this; struct resource *r; @@ -205,7 +205,7 @@ err_get_res: /* * Clean up routine */ -static int __devexit sharpsl_nand_remove(struct platform_device *pdev) +static int sharpsl_nand_remove(struct platform_device *pdev) { struct sharpsl_nand *sharpsl = platform_get_drvdata(pdev); @@ -228,7 +228,7 @@ static struct platform_driver sharpsl_nand_driver = { .owner = THIS_MODULE, }, .probe = sharpsl_nand_probe, - .remove = __devexit_p(sharpsl_nand_remove), + .remove = sharpsl_nand_remove, }; module_platform_driver(sharpsl_nand_driver); diff --git a/drivers/mtd/nand/socrates_nand.c b/drivers/mtd/nand/socrates_nand.c index f3f28fafbf7a..09dde7d27178 100644 --- a/drivers/mtd/nand/socrates_nand.c +++ b/drivers/mtd/nand/socrates_nand.c @@ -140,7 +140,7 @@ static int socrates_nand_device_ready(struct mtd_info *mtd) /* * Probe for the NAND device. */ -static int __devinit socrates_nand_probe(struct platform_device *ofdev) +static int socrates_nand_probe(struct platform_device *ofdev) { struct socrates_nand_host *host; struct mtd_info *mtd; @@ -220,7 +220,7 @@ out: /* * Remove a NAND device. */ -static int __devexit socrates_nand_remove(struct platform_device *ofdev) +static int socrates_nand_remove(struct platform_device *ofdev) { struct socrates_nand_host *host = dev_get_drvdata(&ofdev->dev); struct mtd_info *mtd = &host->mtd; @@ -251,7 +251,7 @@ static struct platform_driver socrates_nand_driver = { .of_match_table = socrates_nand_match, }, .probe = socrates_nand_probe, - .remove = __devexit_p(socrates_nand_remove), + .remove = socrates_nand_remove, }; module_platform_driver(socrates_nand_driver); diff --git a/drivers/mtd/nand/spia.c b/drivers/mtd/nand/spia.c deleted file mode 100644 index bef76cd7c24c..000000000000 --- a/drivers/mtd/nand/spia.c +++ /dev/null @@ -1,176 +0,0 @@ -/* - * drivers/mtd/nand/spia.c - * - * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com) - * - * - * 10-29-2001 TG change to support hardwarespecific access - * to controllines (due to change in nand.c) - * page_cache added - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Overview: - * This is a device driver for the NAND flash device found on the - * SPIA board which utilizes the Toshiba TC58V64AFT part. This is - * a 64Mibit (8MiB x 8 bits) NAND flash device. - */ - -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/mtd/mtd.h> -#include <linux/mtd/nand.h> -#include <linux/mtd/partitions.h> -#include <asm/io.h> - -/* - * MTD structure for SPIA board - */ -static struct mtd_info *spia_mtd = NULL; - -/* - * Values specific to the SPIA board (used with EP7212 processor) - */ -#define SPIA_IO_BASE 0xd0000000 /* Start of EP7212 IO address space */ -#define SPIA_FIO_BASE 0xf0000000 /* Address where flash is mapped */ -#define SPIA_PEDR 0x0080 /* - * IO offset to Port E data register - * where the CLE, ALE and NCE pins - * are wired to. - */ -#define SPIA_PEDDR 0x00c0 /* - * IO offset to Port E data direction - * register so we can control the IO - * lines. - */ - -/* - * Module stuff - */ - -static int spia_io_base = SPIA_IO_BASE; -static int spia_fio_base = SPIA_FIO_BASE; -static int spia_pedr = SPIA_PEDR; -static int spia_peddr = SPIA_PEDDR; - -module_param(spia_io_base, int, 0); -module_param(spia_fio_base, int, 0); -module_param(spia_pedr, int, 0); -module_param(spia_peddr, int, 0); - -/* - * Define partitions for flash device - */ -static const struct mtd_partition partition_info[] = { - { - .name = "SPIA flash partition 1", - .offset = 0, - .size = 2 * 1024 * 1024}, - { - .name = "SPIA flash partition 2", - .offset = 2 * 1024 * 1024, - .size = 6 * 1024 * 1024} -}; - -#define NUM_PARTITIONS 2 - -/* - * hardware specific access to control-lines - * - * ctrl: - * NAND_CNE: bit 0 -> bit 2 - * NAND_CLE: bit 1 -> bit 0 - * NAND_ALE: bit 2 -> bit 1 - */ -static void spia_hwcontrol(struct mtd_info *mtd, int cmd) -{ - struct nand_chip *chip = mtd->priv; - - if (ctrl & NAND_CTRL_CHANGE) { - void __iomem *addr = spia_io_base + spia_pedr; - unsigned char bits; - - bits = (ctrl & NAND_CNE) << 2; - bits |= (ctrl & NAND_CLE | NAND_ALE) >> 1; - writeb((readb(addr) & ~0x7) | bits, addr); - } - - if (cmd != NAND_CMD_NONE) - writeb(cmd, chip->IO_ADDR_W); -} - -/* - * Main initialization routine - */ -static int __init spia_init(void) -{ - struct nand_chip *this; - - /* Allocate memory for MTD device structure and private data */ - spia_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL); - if (!spia_mtd) { - printk("Unable to allocate SPIA NAND MTD device structure.\n"); - return -ENOMEM; - } - - /* Get pointer to private data */ - this = (struct nand_chip *)(&spia_mtd[1]); - - /* Initialize structures */ - memset(spia_mtd, 0, sizeof(struct mtd_info)); - memset(this, 0, sizeof(struct nand_chip)); - - /* Link the private data with the MTD structure */ - spia_mtd->priv = this; - spia_mtd->owner = THIS_MODULE; - - /* - * Set GPIO Port E control register so that the pins are configured - * to be outputs for controlling the NAND flash. - */ - (*(volatile unsigned char *)(spia_io_base + spia_peddr)) = 0x07; - - /* Set address of NAND IO lines */ - this->IO_ADDR_R = (void __iomem *)spia_fio_base; - this->IO_ADDR_W = (void __iomem *)spia_fio_base; - /* Set address of hardware control function */ - this->cmd_ctrl = spia_hwcontrol; - /* 15 us command delay time */ - this->chip_delay = 15; - - /* Scan to find existence of the device */ - if (nand_scan(spia_mtd, 1)) { - kfree(spia_mtd); - return -ENXIO; - } - - /* Register the partitions */ - mtd_device_register(spia_mtd, partition_info, NUM_PARTITIONS); - - /* Return happy */ - return 0; -} - -module_init(spia_init); - -/* - * Clean up routine - */ -static void __exit spia_cleanup(void) -{ - /* Release resources, unregister device */ - nand_release(spia_mtd); - - /* Free the MTD device structure */ - kfree(spia_mtd); -} - -module_exit(spia_cleanup); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Steven J. Hill <sjhill@realitydiluted.com"); -MODULE_DESCRIPTION("Board-specific glue layer for NAND flash on SPIA board"); diff --git a/drivers/mtd/ofpart.c b/drivers/mtd/ofpart.c index 64be8f0848b0..dbd3aa574eaf 100644 --- a/drivers/mtd/ofpart.c +++ b/drivers/mtd/ofpart.c @@ -71,7 +71,10 @@ static int parse_ofpart_partitions(struct mtd_info *master, (*pparts)[i].name = (char *)partname; if (of_get_property(pp, "read-only", &len)) - (*pparts)[i].mask_flags = MTD_WRITEABLE; + (*pparts)[i].mask_flags |= MTD_WRITEABLE; + + if (of_get_property(pp, "lock", &len)) + (*pparts)[i].mask_flags |= MTD_POWERUP_LOCK; i++; } @@ -121,7 +124,7 @@ static int parse_ofoldpart_partitions(struct mtd_info *master, nr_parts = plen / sizeof(part[0]); *pparts = kzalloc(nr_parts * sizeof(*(*pparts)), GFP_KERNEL); - if (!pparts) + if (!*pparts) return -ENOMEM; names = of_get_property(dp, "partition-names", &plen); diff --git a/drivers/mtd/onenand/generic.c b/drivers/mtd/onenand/generic.c index 1c4f97c63e62..9f11562f849d 100644 --- a/drivers/mtd/onenand/generic.c +++ b/drivers/mtd/onenand/generic.c @@ -35,7 +35,7 @@ struct onenand_info { struct onenand_chip onenand; }; -static int __devinit generic_onenand_probe(struct platform_device *pdev) +static int generic_onenand_probe(struct platform_device *pdev) { struct onenand_info *info; struct onenand_platform_data *pdata = pdev->dev.platform_data; @@ -88,7 +88,7 @@ out_free_info: return err; } -static int __devexit generic_onenand_remove(struct platform_device *pdev) +static int generic_onenand_remove(struct platform_device *pdev) { struct onenand_info *info = platform_get_drvdata(pdev); struct resource *res = pdev->resource; @@ -112,7 +112,7 @@ static struct platform_driver generic_onenand_driver = { .owner = THIS_MODULE, }, .probe = generic_onenand_probe, - .remove = __devexit_p(generic_onenand_remove), + .remove = generic_onenand_remove, }; module_platform_driver(generic_onenand_driver); diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c index 1961be985171..065f3fe02a2f 100644 --- a/drivers/mtd/onenand/omap2.c +++ b/drivers/mtd/onenand/omap2.c @@ -38,12 +38,10 @@ #include <linux/regulator/consumer.h> #include <asm/mach/flash.h> -#include <plat/gpmc.h> #include <linux/platform_data/mtd-onenand-omap2.h> #include <asm/gpio.h> -#include <plat/dma.h> -#include <plat/cpu.h> +#include <linux/omap-dma.h> #define DRIVER_NAME "omap2-onenand" @@ -63,6 +61,7 @@ struct omap2_onenand { int freq; int (*setup)(void __iomem *base, int *freq_ptr); struct regulator *regulator; + u8 flags; }; static void omap2_onenand_dma_cb(int lch, u16 ch_status, void *data) @@ -155,7 +154,7 @@ static int omap2_onenand_wait(struct mtd_info *mtd, int state) if (!(syscfg & ONENAND_SYS_CFG1_IOBE)) { syscfg |= ONENAND_SYS_CFG1_IOBE; write_reg(c, syscfg, ONENAND_REG_SYS_CFG1); - if (cpu_is_omap34xx()) + if (c->flags & ONENAND_IN_OMAP34XX) /* Add a delay to let GPIO settle */ syscfg = read_reg(c, ONENAND_REG_SYS_CFG1); } @@ -446,13 +445,19 @@ out_copy: #else -int omap3_onenand_read_bufferram(struct mtd_info *mtd, int area, - unsigned char *buffer, int offset, - size_t count); +static int omap3_onenand_read_bufferram(struct mtd_info *mtd, int area, + unsigned char *buffer, int offset, + size_t count) +{ + return -ENOSYS; +} -int omap3_onenand_write_bufferram(struct mtd_info *mtd, int area, - const unsigned char *buffer, - int offset, size_t count); +static int omap3_onenand_write_bufferram(struct mtd_info *mtd, int area, + const unsigned char *buffer, + int offset, size_t count) +{ + return -ENOSYS; +} #endif @@ -550,13 +555,19 @@ static int omap2_onenand_write_bufferram(struct mtd_info *mtd, int area, #else -int omap2_onenand_read_bufferram(struct mtd_info *mtd, int area, - unsigned char *buffer, int offset, - size_t count); +static int omap2_onenand_read_bufferram(struct mtd_info *mtd, int area, + unsigned char *buffer, int offset, + size_t count) +{ + return -ENOSYS; +} -int omap2_onenand_write_bufferram(struct mtd_info *mtd, int area, - const unsigned char *buffer, - int offset, size_t count); +static int omap2_onenand_write_bufferram(struct mtd_info *mtd, int area, + const unsigned char *buffer, + int offset, size_t count) +{ + return -ENOSYS; +} #endif @@ -619,7 +630,7 @@ static int omap2_onenand_disable(struct mtd_info *mtd) return ret; } -static int __devinit omap2_onenand_probe(struct platform_device *pdev) +static int omap2_onenand_probe(struct platform_device *pdev) { struct omap_onenand_platform_data *pdata; struct omap2_onenand *c; @@ -639,6 +650,7 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev) init_completion(&c->irq_done); init_completion(&c->dma_done); + c->flags = pdata->flags; c->gpmc_cs = pdata->cs; c->gpio_irq = pdata->gpio_irq; c->dma_channel = pdata->dma_channel; @@ -729,7 +741,7 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev) this = &c->onenand; if (c->dma_channel >= 0) { this->wait = omap2_onenand_wait; - if (cpu_is_omap34xx()) { + if (c->flags & ONENAND_IN_OMAP34XX) { this->read_bufferram = omap3_onenand_read_bufferram; this->write_bufferram = omap3_onenand_write_bufferram; } else { @@ -787,7 +799,7 @@ err_kfree: return r; } -static int __devexit omap2_onenand_remove(struct platform_device *pdev) +static int omap2_onenand_remove(struct platform_device *pdev) { struct omap2_onenand *c = dev_get_drvdata(&pdev->dev); @@ -803,7 +815,6 @@ static int __devexit omap2_onenand_remove(struct platform_device *pdev) } iounmap(c->onenand.base); release_mem_region(c->phys_base, c->mem_size); - gpmc_cs_free(c->gpmc_cs); kfree(c); return 0; @@ -811,7 +822,7 @@ static int __devexit omap2_onenand_remove(struct platform_device *pdev) static struct platform_driver omap2_onenand_driver = { .probe = omap2_onenand_probe, - .remove = __devexit_p(omap2_onenand_remove), + .remove = omap2_onenand_remove, .shutdown = omap2_onenand_shutdown, .driver = { .name = DRIVER_NAME, diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index 7153e0d27101..b3f41f200622 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c @@ -3694,7 +3694,7 @@ static int flexonenand_check_blocks_erased(struct mtd_info *mtd, int start, int * flexonenand_set_boundary - Writes the SLC boundary * @param mtd - mtd info structure */ -int flexonenand_set_boundary(struct mtd_info *mtd, int die, +static int flexonenand_set_boundary(struct mtd_info *mtd, int die, int boundary, int lock) { struct onenand_chip *this = mtd->priv; diff --git a/drivers/mtd/onenand/samsung.c b/drivers/mtd/onenand/samsung.c index 8e4b3f2742ba..33f2a8fb8df9 100644 --- a/drivers/mtd/onenand/samsung.c +++ b/drivers/mtd/onenand/samsung.c @@ -1053,7 +1053,7 @@ onenand_fail: return err; } -static int __devexit s3c_onenand_remove(struct platform_device *pdev) +static int s3c_onenand_remove(struct platform_device *pdev) { struct mtd_info *mtd = platform_get_drvdata(pdev); @@ -1130,7 +1130,7 @@ static struct platform_driver s3c_onenand_driver = { }, .id_table = s3c_onenand_driver_ids, .probe = s3c_onenand_probe, - .remove = __devexit_p(s3c_onenand_remove), + .remove = s3c_onenand_remove, }; module_platform_driver(s3c_onenand_driver); diff --git a/drivers/mtd/tests/mtd_nandbiterrs.c b/drivers/mtd/tests/mtd_nandbiterrs.c index cc8d62cb280c..207bf9a9972f 100644 --- a/drivers/mtd/tests/mtd_nandbiterrs.c +++ b/drivers/mtd/tests/mtd_nandbiterrs.c @@ -39,6 +39,9 @@ * this program; see the file COPYING. If not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/init.h> #include <linux/module.h> #include <linux/moduleparam.h> @@ -47,8 +50,6 @@ #include <linux/mtd/nand.h> #include <linux/slab.h> -#define msg(FMT, VA...) pr_info("mtd_nandbiterrs: "FMT, ##VA) - static int dev; module_param(dev, int, S_IRUGO); MODULE_PARM_DESC(dev, "MTD device number to use"); @@ -103,7 +104,7 @@ static int erase_block(void) struct erase_info ei; loff_t addr = eraseblock * mtd->erasesize; - msg("erase_block\n"); + pr_info("erase_block\n"); memset(&ei, 0, sizeof(struct erase_info)); ei.mtd = mtd; @@ -112,7 +113,7 @@ static int erase_block(void) err = mtd_erase(mtd, &ei); if (err || ei.state == MTD_ERASE_FAILED) { - msg("error %d while erasing\n", err); + pr_err("error %d while erasing\n", err); if (!err) err = -EIO; return err; @@ -128,11 +129,11 @@ static int write_page(int log) size_t written; if (log) - msg("write_page\n"); + pr_info("write_page\n"); err = mtd_write(mtd, offset, mtd->writesize, &written, wbuffer); if (err || written != mtd->writesize) { - msg("error: write failed at %#llx\n", (long long)offset); + pr_err("error: write failed at %#llx\n", (long long)offset); if (!err) err = -EIO; } @@ -147,7 +148,7 @@ static int rewrite_page(int log) struct mtd_oob_ops ops; if (log) - msg("rewrite page\n"); + pr_info("rewrite page\n"); ops.mode = MTD_OPS_RAW; /* No ECC */ ops.len = mtd->writesize; @@ -160,7 +161,7 @@ static int rewrite_page(int log) err = mtd_write_oob(mtd, offset, &ops); if (err || ops.retlen != mtd->writesize) { - msg("error: write_oob failed (%d)\n", err); + pr_err("error: write_oob failed (%d)\n", err); if (!err) err = -EIO; } @@ -177,7 +178,7 @@ static int read_page(int log) struct mtd_ecc_stats oldstats; if (log) - msg("read_page\n"); + pr_info("read_page\n"); /* Saving last mtd stats */ memcpy(&oldstats, &mtd->ecc_stats, sizeof(oldstats)); @@ -187,7 +188,7 @@ static int read_page(int log) err = mtd->ecc_stats.corrected - oldstats.corrected; if (err < 0 || read != mtd->writesize) { - msg("error: read failed at %#llx\n", (long long)offset); + pr_err("error: read failed at %#llx\n", (long long)offset); if (err >= 0) err = -EIO; } @@ -201,11 +202,11 @@ static int verify_page(int log) unsigned i, errs = 0; if (log) - msg("verify_page\n"); + pr_info("verify_page\n"); for (i = 0; i < mtd->writesize; i++) { if (rbuffer[i] != hash(i+seed)) { - msg("Error: page offset %u, expected %02x, got %02x\n", + pr_err("Error: page offset %u, expected %02x, got %02x\n", i, hash(i+seed), rbuffer[i]); errs++; } @@ -230,13 +231,13 @@ static int insert_biterror(unsigned byte) for (bit = 7; bit >= 0; bit--) { if (CBIT(wbuffer[byte], bit)) { BCLR(wbuffer[byte], bit); - msg("Inserted biterror @ %u/%u\n", byte, bit); + pr_info("Inserted biterror @ %u/%u\n", byte, bit); return 0; } } byte++; } - msg("biterror: Failed to find a '1' bit\n"); + pr_err("biterror: Failed to find a '1' bit\n"); return -EIO; } @@ -248,7 +249,7 @@ static int incremental_errors_test(void) unsigned i; unsigned errs_per_subpage = 0; - msg("incremental biterrors test\n"); + pr_info("incremental biterrors test\n"); for (i = 0; i < mtd->writesize; i++) wbuffer[i] = hash(i+seed); @@ -265,9 +266,9 @@ static int incremental_errors_test(void) err = read_page(1); if (err > 0) - msg("Read reported %d corrected bit errors\n", err); + pr_info("Read reported %d corrected bit errors\n", err); if (err < 0) { - msg("After %d biterrors per subpage, read reported error %d\n", + pr_err("After %d biterrors per subpage, read reported error %d\n", errs_per_subpage, err); err = 0; goto exit; @@ -275,11 +276,11 @@ static int incremental_errors_test(void) err = verify_page(1); if (err) { - msg("ECC failure, read data is incorrect despite read success\n"); + pr_err("ECC failure, read data is incorrect despite read success\n"); goto exit; } - msg("Successfully corrected %d bit errors per subpage\n", + pr_info("Successfully corrected %d bit errors per subpage\n", errs_per_subpage); for (i = 0; i < subcount; i++) { @@ -311,7 +312,7 @@ static int overwrite_test(void) memset(bitstats, 0, sizeof(bitstats)); - msg("overwrite biterrors test\n"); + pr_info("overwrite biterrors test\n"); for (i = 0; i < mtd->writesize; i++) wbuffer[i] = hash(i+seed); @@ -329,18 +330,18 @@ static int overwrite_test(void) err = read_page(0); if (err >= 0) { if (err >= MAXBITS) { - msg("Implausible number of bit errors corrected\n"); + pr_info("Implausible number of bit errors corrected\n"); err = -EIO; break; } bitstats[err]++; if (err > max_corrected) { max_corrected = err; - msg("Read reported %d corrected bit errors\n", + pr_info("Read reported %d corrected bit errors\n", err); } } else { /* err < 0 */ - msg("Read reported error %d\n", err); + pr_info("Read reported error %d\n", err); err = 0; break; } @@ -348,7 +349,7 @@ static int overwrite_test(void) err = verify_page(0); if (err) { bitstats[max_corrected] = opno; - msg("ECC failure, read data is incorrect despite read success\n"); + pr_info("ECC failure, read data is incorrect despite read success\n"); break; } @@ -357,9 +358,9 @@ static int overwrite_test(void) /* At this point bitstats[0] contains the number of ops with no bit * errors, bitstats[1] the number of ops with 1 bit error, etc. */ - msg("Bit error histogram (%d operations total):\n", opno); + pr_info("Bit error histogram (%d operations total):\n", opno); for (i = 0; i < max_corrected; i++) - msg("Page reads with %3d corrected bit errors: %d\n", + pr_info("Page reads with %3d corrected bit errors: %d\n", i, bitstats[i]); exit: @@ -370,36 +371,36 @@ static int __init mtd_nandbiterrs_init(void) { int err = 0; - msg("\n"); - msg("==================================================\n"); - msg("MTD device: %d\n", dev); + printk("\n"); + printk(KERN_INFO "==================================================\n"); + pr_info("MTD device: %d\n", dev); mtd = get_mtd_device(NULL, dev); if (IS_ERR(mtd)) { err = PTR_ERR(mtd); - msg("error: cannot get MTD device\n"); + pr_err("error: cannot get MTD device\n"); goto exit_mtddev; } if (mtd->type != MTD_NANDFLASH) { - msg("this test requires NAND flash\n"); + pr_info("this test requires NAND flash\n"); err = -ENODEV; goto exit_nand; } - msg("MTD device size %llu, eraseblock=%u, page=%u, oob=%u\n", + pr_info("MTD device size %llu, eraseblock=%u, page=%u, oob=%u\n", (unsigned long long)mtd->size, mtd->erasesize, mtd->writesize, mtd->oobsize); subsize = mtd->writesize >> mtd->subpage_sft; subcount = mtd->writesize / subsize; - msg("Device uses %d subpages of %d bytes\n", subcount, subsize); + pr_info("Device uses %d subpages of %d bytes\n", subcount, subsize); offset = page_offset * mtd->writesize; eraseblock = mtd_div_by_eb(offset, mtd); - msg("Using page=%u, offset=%llu, eraseblock=%u\n", + pr_info("Using page=%u, offset=%llu, eraseblock=%u\n", page_offset, offset, eraseblock); wbuffer = kmalloc(mtd->writesize, GFP_KERNEL); @@ -432,8 +433,8 @@ static int __init mtd_nandbiterrs_init(void) goto exit_error; err = -EIO; - msg("finished successfully.\n"); - msg("==================================================\n"); + pr_info("finished successfully.\n"); + printk(KERN_INFO "==================================================\n"); exit_error: kfree(rbuffer); diff --git a/drivers/mtd/tests/mtd_nandecctest.c b/drivers/mtd/tests/mtd_nandecctest.c index b437fa425077..1eee264509a8 100644 --- a/drivers/mtd/tests/mtd_nandecctest.c +++ b/drivers/mtd/tests/mtd_nandecctest.c @@ -1,3 +1,5 @@ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/kernel.h> #include <linux/module.h> #include <linux/list.h> @@ -264,13 +266,13 @@ static int nand_ecc_test_run(const size_t size) correct_data, size); if (err) { - pr_err("mtd_nandecctest: not ok - %s-%zd\n", + pr_err("not ok - %s-%zd\n", nand_ecc_test[i].name, size); dump_data_ecc(error_data, error_ecc, correct_data, correct_ecc, size); break; } - pr_info("mtd_nandecctest: ok - %s-%zd\n", + pr_info("ok - %s-%zd\n", nand_ecc_test[i].name, size); } error: diff --git a/drivers/mtd/tests/mtd_oobtest.c b/drivers/mtd/tests/mtd_oobtest.c index ed9b62827f1b..e827fa8cd844 100644 --- a/drivers/mtd/tests/mtd_oobtest.c +++ b/drivers/mtd/tests/mtd_oobtest.c @@ -19,6 +19,8 @@ * Author: Adrian Hunter <ext-adrian.hunter@nokia.com> */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <asm/div64.h> #include <linux/init.h> #include <linux/module.h> @@ -28,8 +30,6 @@ #include <linux/slab.h> #include <linux/sched.h> -#define PRINT_PREF KERN_INFO "mtd_oobtest: " - static int dev = -EINVAL; module_param(dev, int, S_IRUGO); MODULE_PARM_DESC(dev, "MTD device number to use"); @@ -80,13 +80,12 @@ static int erase_eraseblock(int ebnum) err = mtd_erase(mtd, &ei); if (err) { - printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum); + pr_err("error %d while erasing EB %d\n", err, ebnum); return err; } if (ei.state == MTD_ERASE_FAILED) { - printk(PRINT_PREF "some erase error occurred at EB %d\n", - ebnum); + pr_err("some erase error occurred at EB %d\n", ebnum); return -EIO; } @@ -98,7 +97,7 @@ static int erase_whole_device(void) int err; unsigned int i; - printk(PRINT_PREF "erasing whole device\n"); + pr_info("erasing whole device\n"); for (i = 0; i < ebcnt; ++i) { if (bbt[i]) continue; @@ -107,7 +106,7 @@ static int erase_whole_device(void) return err; cond_resched(); } - printk(PRINT_PREF "erased %u eraseblocks\n", i); + pr_info("erased %u eraseblocks\n", i); return 0; } @@ -141,9 +140,9 @@ static int write_eraseblock(int ebnum) ops.oobbuf = writebuf; err = mtd_write_oob(mtd, addr, &ops); if (err || ops.oobretlen != use_len) { - printk(PRINT_PREF "error: writeoob failed at %#llx\n", + pr_err("error: writeoob failed at %#llx\n", (long long)addr); - printk(PRINT_PREF "error: use_len %d, use_offset %d\n", + pr_err("error: use_len %d, use_offset %d\n", use_len, use_offset); errcnt += 1; return err ? err : -1; @@ -160,7 +159,7 @@ static int write_whole_device(void) int err; unsigned int i; - printk(PRINT_PREF "writing OOBs of whole device\n"); + pr_info("writing OOBs of whole device\n"); for (i = 0; i < ebcnt; ++i) { if (bbt[i]) continue; @@ -168,10 +167,10 @@ static int write_whole_device(void) if (err) return err; if (i % 256 == 0) - printk(PRINT_PREF "written up to eraseblock %u\n", i); + pr_info("written up to eraseblock %u\n", i); cond_resched(); } - printk(PRINT_PREF "written %u eraseblocks\n", i); + pr_info("written %u eraseblocks\n", i); return 0; } @@ -194,17 +193,17 @@ static int verify_eraseblock(int ebnum) ops.oobbuf = readbuf; err = mtd_read_oob(mtd, addr, &ops); if (err || ops.oobretlen != use_len) { - printk(PRINT_PREF "error: readoob failed at %#llx\n", + pr_err("error: readoob failed at %#llx\n", (long long)addr); errcnt += 1; return err ? err : -1; } if (memcmp(readbuf, writebuf, use_len)) { - printk(PRINT_PREF "error: verify failed at %#llx\n", + pr_err("error: verify failed at %#llx\n", (long long)addr); errcnt += 1; if (errcnt > 1000) { - printk(PRINT_PREF "error: too many errors\n"); + pr_err("error: too many errors\n"); return -1; } } @@ -221,29 +220,28 @@ static int verify_eraseblock(int ebnum) ops.oobbuf = readbuf; err = mtd_read_oob(mtd, addr, &ops); if (err || ops.oobretlen != mtd->ecclayout->oobavail) { - printk(PRINT_PREF "error: readoob failed at " - "%#llx\n", (long long)addr); + pr_err("error: readoob failed at %#llx\n", + (long long)addr); errcnt += 1; return err ? err : -1; } if (memcmp(readbuf + use_offset, writebuf, use_len)) { - printk(PRINT_PREF "error: verify failed at " - "%#llx\n", (long long)addr); + pr_err("error: verify failed at %#llx\n", + (long long)addr); errcnt += 1; if (errcnt > 1000) { - printk(PRINT_PREF "error: too many " - "errors\n"); + pr_err("error: too many errors\n"); return -1; } } for (k = 0; k < use_offset; ++k) if (readbuf[k] != 0xff) { - printk(PRINT_PREF "error: verify 0xff " + pr_err("error: verify 0xff " "failed at %#llx\n", (long long)addr); errcnt += 1; if (errcnt > 1000) { - printk(PRINT_PREF "error: too " + pr_err("error: too " "many errors\n"); return -1; } @@ -251,12 +249,12 @@ static int verify_eraseblock(int ebnum) for (k = use_offset + use_len; k < mtd->ecclayout->oobavail; ++k) if (readbuf[k] != 0xff) { - printk(PRINT_PREF "error: verify 0xff " + pr_err("error: verify 0xff " "failed at %#llx\n", (long long)addr); errcnt += 1; if (errcnt > 1000) { - printk(PRINT_PREF "error: too " + pr_err("error: too " "many errors\n"); return -1; } @@ -286,17 +284,17 @@ static int verify_eraseblock_in_one_go(int ebnum) ops.oobbuf = readbuf; err = mtd_read_oob(mtd, addr, &ops); if (err || ops.oobretlen != len) { - printk(PRINT_PREF "error: readoob failed at %#llx\n", + pr_err("error: readoob failed at %#llx\n", (long long)addr); errcnt += 1; return err ? err : -1; } if (memcmp(readbuf, writebuf, len)) { - printk(PRINT_PREF "error: verify failed at %#llx\n", + pr_err("error: verify failed at %#llx\n", (long long)addr); errcnt += 1; if (errcnt > 1000) { - printk(PRINT_PREF "error: too many errors\n"); + pr_err("error: too many errors\n"); return -1; } } @@ -309,7 +307,7 @@ static int verify_all_eraseblocks(void) int err; unsigned int i; - printk(PRINT_PREF "verifying all eraseblocks\n"); + pr_info("verifying all eraseblocks\n"); for (i = 0; i < ebcnt; ++i) { if (bbt[i]) continue; @@ -317,10 +315,10 @@ static int verify_all_eraseblocks(void) if (err) return err; if (i % 256 == 0) - printk(PRINT_PREF "verified up to eraseblock %u\n", i); + pr_info("verified up to eraseblock %u\n", i); cond_resched(); } - printk(PRINT_PREF "verified %u eraseblocks\n", i); + pr_info("verified %u eraseblocks\n", i); return 0; } @@ -331,7 +329,7 @@ static int is_block_bad(int ebnum) ret = mtd_block_isbad(mtd, addr); if (ret) - printk(PRINT_PREF "block %d is bad\n", ebnum); + pr_info("block %d is bad\n", ebnum); return ret; } @@ -341,18 +339,18 @@ static int scan_for_bad_eraseblocks(void) bbt = kmalloc(ebcnt, GFP_KERNEL); if (!bbt) { - printk(PRINT_PREF "error: cannot allocate memory\n"); + pr_err("error: cannot allocate memory\n"); return -ENOMEM; } - printk(PRINT_PREF "scanning for bad eraseblocks\n"); + pr_info("scanning for bad eraseblocks\n"); for (i = 0; i < ebcnt; ++i) { bbt[i] = is_block_bad(i) ? 1 : 0; if (bbt[i]) bad += 1; cond_resched(); } - printk(PRINT_PREF "scanned %d eraseblocks, %d are bad\n", i, bad); + pr_info("scanned %d eraseblocks, %d are bad\n", i, bad); return 0; } @@ -368,22 +366,22 @@ static int __init mtd_oobtest_init(void) printk(KERN_INFO "=================================================\n"); if (dev < 0) { - printk(PRINT_PREF "Please specify a valid mtd-device via module paramter\n"); - printk(KERN_CRIT "CAREFUL: This test wipes all data on the specified MTD device!\n"); + pr_info("Please specify a valid mtd-device via module parameter\n"); + pr_crit("CAREFUL: This test wipes all data on the specified MTD device!\n"); return -EINVAL; } - printk(PRINT_PREF "MTD device: %d\n", dev); + pr_info("MTD device: %d\n", dev); mtd = get_mtd_device(NULL, dev); if (IS_ERR(mtd)) { err = PTR_ERR(mtd); - printk(PRINT_PREF "error: cannot get MTD device\n"); + pr_err("error: cannot get MTD device\n"); return err; } if (mtd->type != MTD_NANDFLASH) { - printk(PRINT_PREF "this test requires NAND flash\n"); + pr_info("this test requires NAND flash\n"); goto out; } @@ -392,7 +390,7 @@ static int __init mtd_oobtest_init(void) ebcnt = tmp; pgcnt = mtd->erasesize / mtd->writesize; - printk(PRINT_PREF "MTD device size %llu, eraseblock size %u, " + pr_info("MTD device size %llu, eraseblock size %u, " "page size %u, count of eraseblocks %u, pages per " "eraseblock %u, OOB size %u\n", (unsigned long long)mtd->size, mtd->erasesize, @@ -401,12 +399,12 @@ static int __init mtd_oobtest_init(void) err = -ENOMEM; readbuf = kmalloc(mtd->erasesize, GFP_KERNEL); if (!readbuf) { - printk(PRINT_PREF "error: cannot allocate memory\n"); + pr_err("error: cannot allocate memory\n"); goto out; } writebuf = kmalloc(mtd->erasesize, GFP_KERNEL); if (!writebuf) { - printk(PRINT_PREF "error: cannot allocate memory\n"); + pr_err("error: cannot allocate memory\n"); goto out; } @@ -420,7 +418,7 @@ static int __init mtd_oobtest_init(void) vary_offset = 0; /* First test: write all OOB, read it back and verify */ - printk(PRINT_PREF "test 1 of 5\n"); + pr_info("test 1 of 5\n"); err = erase_whole_device(); if (err) @@ -440,7 +438,7 @@ static int __init mtd_oobtest_init(void) * Second test: write all OOB, a block at a time, read it back and * verify. */ - printk(PRINT_PREF "test 2 of 5\n"); + pr_info("test 2 of 5\n"); err = erase_whole_device(); if (err) @@ -453,7 +451,7 @@ static int __init mtd_oobtest_init(void) /* Check all eraseblocks */ simple_srand(3); - printk(PRINT_PREF "verifying all eraseblocks\n"); + pr_info("verifying all eraseblocks\n"); for (i = 0; i < ebcnt; ++i) { if (bbt[i]) continue; @@ -461,16 +459,16 @@ static int __init mtd_oobtest_init(void) if (err) goto out; if (i % 256 == 0) - printk(PRINT_PREF "verified up to eraseblock %u\n", i); + pr_info("verified up to eraseblock %u\n", i); cond_resched(); } - printk(PRINT_PREF "verified %u eraseblocks\n", i); + pr_info("verified %u eraseblocks\n", i); /* * Third test: write OOB at varying offsets and lengths, read it back * and verify. */ - printk(PRINT_PREF "test 3 of 5\n"); + pr_info("test 3 of 5\n"); err = erase_whole_device(); if (err) @@ -503,7 +501,7 @@ static int __init mtd_oobtest_init(void) vary_offset = 0; /* Fourth test: try to write off end of device */ - printk(PRINT_PREF "test 4 of 5\n"); + pr_info("test 4 of 5\n"); err = erase_whole_device(); if (err) @@ -522,14 +520,14 @@ static int __init mtd_oobtest_init(void) ops.ooboffs = mtd->ecclayout->oobavail; ops.datbuf = NULL; ops.oobbuf = writebuf; - printk(PRINT_PREF "attempting to start write past end of OOB\n"); - printk(PRINT_PREF "an error is expected...\n"); + pr_info("attempting to start write past end of OOB\n"); + pr_info("an error is expected...\n"); err = mtd_write_oob(mtd, addr0, &ops); if (err) { - printk(PRINT_PREF "error occurred as expected\n"); + pr_info("error occurred as expected\n"); err = 0; } else { - printk(PRINT_PREF "error: can write past end of OOB\n"); + pr_err("error: can write past end of OOB\n"); errcnt += 1; } @@ -542,19 +540,19 @@ static int __init mtd_oobtest_init(void) ops.ooboffs = mtd->ecclayout->oobavail; ops.datbuf = NULL; ops.oobbuf = readbuf; - printk(PRINT_PREF "attempting to start read past end of OOB\n"); - printk(PRINT_PREF "an error is expected...\n"); + pr_info("attempting to start read past end of OOB\n"); + pr_info("an error is expected...\n"); err = mtd_read_oob(mtd, addr0, &ops); if (err) { - printk(PRINT_PREF "error occurred as expected\n"); + pr_info("error occurred as expected\n"); err = 0; } else { - printk(PRINT_PREF "error: can read past end of OOB\n"); + pr_err("error: can read past end of OOB\n"); errcnt += 1; } if (bbt[ebcnt - 1]) - printk(PRINT_PREF "skipping end of device tests because last " + pr_info("skipping end of device tests because last " "block is bad\n"); else { /* Attempt to write off end of device */ @@ -566,14 +564,14 @@ static int __init mtd_oobtest_init(void) ops.ooboffs = 0; ops.datbuf = NULL; ops.oobbuf = writebuf; - printk(PRINT_PREF "attempting to write past end of device\n"); - printk(PRINT_PREF "an error is expected...\n"); + pr_info("attempting to write past end of device\n"); + pr_info("an error is expected...\n"); err = mtd_write_oob(mtd, mtd->size - mtd->writesize, &ops); if (err) { - printk(PRINT_PREF "error occurred as expected\n"); + pr_info("error occurred as expected\n"); err = 0; } else { - printk(PRINT_PREF "error: wrote past end of device\n"); + pr_err("error: wrote past end of device\n"); errcnt += 1; } @@ -586,14 +584,14 @@ static int __init mtd_oobtest_init(void) ops.ooboffs = 0; ops.datbuf = NULL; ops.oobbuf = readbuf; - printk(PRINT_PREF "attempting to read past end of device\n"); - printk(PRINT_PREF "an error is expected...\n"); + pr_info("attempting to read past end of device\n"); + pr_info("an error is expected...\n"); err = mtd_read_oob(mtd, mtd->size - mtd->writesize, &ops); if (err) { - printk(PRINT_PREF "error occurred as expected\n"); + pr_info("error occurred as expected\n"); err = 0; } else { - printk(PRINT_PREF "error: read past end of device\n"); + pr_err("error: read past end of device\n"); errcnt += 1; } @@ -610,14 +608,14 @@ static int __init mtd_oobtest_init(void) ops.ooboffs = 1; ops.datbuf = NULL; ops.oobbuf = writebuf; - printk(PRINT_PREF "attempting to write past end of device\n"); - printk(PRINT_PREF "an error is expected...\n"); + pr_info("attempting to write past end of device\n"); + pr_info("an error is expected...\n"); err = mtd_write_oob(mtd, mtd->size - mtd->writesize, &ops); if (err) { - printk(PRINT_PREF "error occurred as expected\n"); + pr_info("error occurred as expected\n"); err = 0; } else { - printk(PRINT_PREF "error: wrote past end of device\n"); + pr_err("error: wrote past end of device\n"); errcnt += 1; } @@ -630,20 +628,20 @@ static int __init mtd_oobtest_init(void) ops.ooboffs = 1; ops.datbuf = NULL; ops.oobbuf = readbuf; - printk(PRINT_PREF "attempting to read past end of device\n"); - printk(PRINT_PREF "an error is expected...\n"); + pr_info("attempting to read past end of device\n"); + pr_info("an error is expected...\n"); err = mtd_read_oob(mtd, mtd->size - mtd->writesize, &ops); if (err) { - printk(PRINT_PREF "error occurred as expected\n"); + pr_info("error occurred as expected\n"); err = 0; } else { - printk(PRINT_PREF "error: read past end of device\n"); + pr_err("error: read past end of device\n"); errcnt += 1; } } /* Fifth test: write / read across block boundaries */ - printk(PRINT_PREF "test 5 of 5\n"); + pr_info("test 5 of 5\n"); /* Erase all eraseblocks */ err = erase_whole_device(); @@ -652,7 +650,7 @@ static int __init mtd_oobtest_init(void) /* Write all eraseblocks */ simple_srand(11); - printk(PRINT_PREF "writing OOBs of whole device\n"); + pr_info("writing OOBs of whole device\n"); for (i = 0; i < ebcnt - 1; ++i) { int cnt = 2; int pg; @@ -674,17 +672,16 @@ static int __init mtd_oobtest_init(void) if (err) goto out; if (i % 256 == 0) - printk(PRINT_PREF "written up to eraseblock " - "%u\n", i); + pr_info("written up to eraseblock %u\n", i); cond_resched(); addr += mtd->writesize; } } - printk(PRINT_PREF "written %u eraseblocks\n", i); + pr_info("written %u eraseblocks\n", i); /* Check all eraseblocks */ simple_srand(11); - printk(PRINT_PREF "verifying all eraseblocks\n"); + pr_info("verifying all eraseblocks\n"); for (i = 0; i < ebcnt - 1; ++i) { if (bbt[i] || bbt[i + 1]) continue; @@ -702,28 +699,28 @@ static int __init mtd_oobtest_init(void) if (err) goto out; if (memcmp(readbuf, writebuf, mtd->ecclayout->oobavail * 2)) { - printk(PRINT_PREF "error: verify failed at %#llx\n", + pr_err("error: verify failed at %#llx\n", (long long)addr); errcnt += 1; if (errcnt > 1000) { - printk(PRINT_PREF "error: too many errors\n"); + pr_err("error: too many errors\n"); goto out; } } if (i % 256 == 0) - printk(PRINT_PREF "verified up to eraseblock %u\n", i); + pr_info("verified up to eraseblock %u\n", i); cond_resched(); } - printk(PRINT_PREF "verified %u eraseblocks\n", i); + pr_info("verified %u eraseblocks\n", i); - printk(PRINT_PREF "finished with %d errors\n", errcnt); + pr_info("finished with %d errors\n", errcnt); out: kfree(bbt); kfree(writebuf); kfree(readbuf); put_mtd_device(mtd); if (err) - printk(PRINT_PREF "error %d occurred\n", err); + pr_info("error %d occurred\n", err); printk(KERN_INFO "=================================================\n"); return err; } diff --git a/drivers/mtd/tests/mtd_pagetest.c b/drivers/mtd/tests/mtd_pagetest.c index 252ddb092fb2..f93a76f88113 100644 --- a/drivers/mtd/tests/mtd_pagetest.c +++ b/drivers/mtd/tests/mtd_pagetest.c @@ -19,6 +19,8 @@ * Author: Adrian Hunter <ext-adrian.hunter@nokia.com> */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <asm/div64.h> #include <linux/init.h> #include <linux/module.h> @@ -28,8 +30,6 @@ #include <linux/slab.h> #include <linux/sched.h> -#define PRINT_PREF KERN_INFO "mtd_pagetest: " - static int dev = -EINVAL; module_param(dev, int, S_IRUGO); MODULE_PARM_DESC(dev, "MTD device number to use"); @@ -79,12 +79,12 @@ static int erase_eraseblock(int ebnum) err = mtd_erase(mtd, &ei); if (err) { - printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum); + pr_err("error %d while erasing EB %d\n", err, ebnum); return err; } if (ei.state == MTD_ERASE_FAILED) { - printk(PRINT_PREF "some erase error occurred at EB %d\n", + pr_err("some erase error occurred at EB %d\n", ebnum); return -EIO; } @@ -102,7 +102,7 @@ static int write_eraseblock(int ebnum) cond_resched(); err = mtd_write(mtd, addr, mtd->erasesize, &written, writebuf); if (err || written != mtd->erasesize) - printk(PRINT_PREF "error: write failed at %#llx\n", + pr_err("error: write failed at %#llx\n", (long long)addr); return err; @@ -131,7 +131,7 @@ static int verify_eraseblock(int ebnum) if (mtd_is_bitflip(err)) err = 0; if (err || read != bufsize) { - printk(PRINT_PREF "error: read failed at %#llx\n", + pr_err("error: read failed at %#llx\n", (long long)addr0); return err; } @@ -139,7 +139,7 @@ static int verify_eraseblock(int ebnum) if (mtd_is_bitflip(err)) err = 0; if (err || read != bufsize) { - printk(PRINT_PREF "error: read failed at %#llx\n", + pr_err("error: read failed at %#llx\n", (long long)(addrn - bufsize)); return err; } @@ -148,12 +148,12 @@ static int verify_eraseblock(int ebnum) if (mtd_is_bitflip(err)) err = 0; if (err || read != bufsize) { - printk(PRINT_PREF "error: read failed at %#llx\n", + pr_err("error: read failed at %#llx\n", (long long)addr); break; } if (memcmp(twopages, writebuf + (j * pgsize), bufsize)) { - printk(PRINT_PREF "error: verify failed at %#llx\n", + pr_err("error: verify failed at %#llx\n", (long long)addr); errcnt += 1; } @@ -166,7 +166,7 @@ static int verify_eraseblock(int ebnum) if (mtd_is_bitflip(err)) err = 0; if (err || read != bufsize) { - printk(PRINT_PREF "error: read failed at %#llx\n", + pr_err("error: read failed at %#llx\n", (long long)addr0); return err; } @@ -174,7 +174,7 @@ static int verify_eraseblock(int ebnum) if (mtd_is_bitflip(err)) err = 0; if (err || read != bufsize) { - printk(PRINT_PREF "error: read failed at %#llx\n", + pr_err("error: read failed at %#llx\n", (long long)(addrn - bufsize)); return err; } @@ -183,14 +183,14 @@ static int verify_eraseblock(int ebnum) if (mtd_is_bitflip(err)) err = 0; if (err || read != bufsize) { - printk(PRINT_PREF "error: read failed at %#llx\n", + pr_err("error: read failed at %#llx\n", (long long)addr); return err; } memcpy(boundary, writebuf + mtd->erasesize - pgsize, pgsize); set_random_data(boundary + pgsize, pgsize); if (memcmp(twopages, boundary, bufsize)) { - printk(PRINT_PREF "error: verify failed at %#llx\n", + pr_err("error: verify failed at %#llx\n", (long long)addr); errcnt += 1; } @@ -206,10 +206,10 @@ static int crosstest(void) loff_t addr, addr0, addrn; unsigned char *pp1, *pp2, *pp3, *pp4; - printk(PRINT_PREF "crosstest\n"); + pr_info("crosstest\n"); pp1 = kmalloc(pgsize * 4, GFP_KERNEL); if (!pp1) { - printk(PRINT_PREF "error: cannot allocate memory\n"); + pr_err("error: cannot allocate memory\n"); return -ENOMEM; } pp2 = pp1 + pgsize; @@ -231,7 +231,7 @@ static int crosstest(void) if (mtd_is_bitflip(err)) err = 0; if (err || read != pgsize) { - printk(PRINT_PREF "error: read failed at %#llx\n", + pr_err("error: read failed at %#llx\n", (long long)addr); kfree(pp1); return err; @@ -243,7 +243,7 @@ static int crosstest(void) if (mtd_is_bitflip(err)) err = 0; if (err || read != pgsize) { - printk(PRINT_PREF "error: read failed at %#llx\n", + pr_err("error: read failed at %#llx\n", (long long)addr); kfree(pp1); return err; @@ -251,12 +251,12 @@ static int crosstest(void) /* Read first page to pp2 */ addr = addr0; - printk(PRINT_PREF "reading page at %#llx\n", (long long)addr); + pr_info("reading page at %#llx\n", (long long)addr); err = mtd_read(mtd, addr, pgsize, &read, pp2); if (mtd_is_bitflip(err)) err = 0; if (err || read != pgsize) { - printk(PRINT_PREF "error: read failed at %#llx\n", + pr_err("error: read failed at %#llx\n", (long long)addr); kfree(pp1); return err; @@ -264,12 +264,12 @@ static int crosstest(void) /* Read last page to pp3 */ addr = addrn - pgsize; - printk(PRINT_PREF "reading page at %#llx\n", (long long)addr); + pr_info("reading page at %#llx\n", (long long)addr); err = mtd_read(mtd, addr, pgsize, &read, pp3); if (mtd_is_bitflip(err)) err = 0; if (err || read != pgsize) { - printk(PRINT_PREF "error: read failed at %#llx\n", + pr_err("error: read failed at %#llx\n", (long long)addr); kfree(pp1); return err; @@ -277,25 +277,25 @@ static int crosstest(void) /* Read first page again to pp4 */ addr = addr0; - printk(PRINT_PREF "reading page at %#llx\n", (long long)addr); + pr_info("reading page at %#llx\n", (long long)addr); err = mtd_read(mtd, addr, pgsize, &read, pp4); if (mtd_is_bitflip(err)) err = 0; if (err || read != pgsize) { - printk(PRINT_PREF "error: read failed at %#llx\n", + pr_err("error: read failed at %#llx\n", (long long)addr); kfree(pp1); return err; } /* pp2 and pp4 should be the same */ - printk(PRINT_PREF "verifying pages read at %#llx match\n", + pr_info("verifying pages read at %#llx match\n", (long long)addr0); if (memcmp(pp2, pp4, pgsize)) { - printk(PRINT_PREF "verify failed!\n"); + pr_err("verify failed!\n"); errcnt += 1; } else if (!err) - printk(PRINT_PREF "crosstest ok\n"); + pr_info("crosstest ok\n"); kfree(pp1); return err; } @@ -307,7 +307,7 @@ static int erasecrosstest(void) loff_t addr0; char *readbuf = twopages; - printk(PRINT_PREF "erasecrosstest\n"); + pr_info("erasecrosstest\n"); ebnum = 0; addr0 = 0; @@ -320,79 +320,79 @@ static int erasecrosstest(void) while (ebnum2 && bbt[ebnum2]) ebnum2 -= 1; - printk(PRINT_PREF "erasing block %d\n", ebnum); + pr_info("erasing block %d\n", ebnum); err = erase_eraseblock(ebnum); if (err) return err; - printk(PRINT_PREF "writing 1st page of block %d\n", ebnum); + pr_info("writing 1st page of block %d\n", ebnum); set_random_data(writebuf, pgsize); strcpy(writebuf, "There is no data like this!"); err = mtd_write(mtd, addr0, pgsize, &written, writebuf); if (err || written != pgsize) { - printk(PRINT_PREF "error: write failed at %#llx\n", + pr_info("error: write failed at %#llx\n", (long long)addr0); return err ? err : -1; } - printk(PRINT_PREF "reading 1st page of block %d\n", ebnum); + pr_info("reading 1st page of block %d\n", ebnum); memset(readbuf, 0, pgsize); err = mtd_read(mtd, addr0, pgsize, &read, readbuf); if (mtd_is_bitflip(err)) err = 0; if (err || read != pgsize) { - printk(PRINT_PREF "error: read failed at %#llx\n", + pr_err("error: read failed at %#llx\n", (long long)addr0); return err ? err : -1; } - printk(PRINT_PREF "verifying 1st page of block %d\n", ebnum); + pr_info("verifying 1st page of block %d\n", ebnum); if (memcmp(writebuf, readbuf, pgsize)) { - printk(PRINT_PREF "verify failed!\n"); + pr_err("verify failed!\n"); errcnt += 1; return -1; } - printk(PRINT_PREF "erasing block %d\n", ebnum); + pr_info("erasing block %d\n", ebnum); err = erase_eraseblock(ebnum); if (err) return err; - printk(PRINT_PREF "writing 1st page of block %d\n", ebnum); + pr_info("writing 1st page of block %d\n", ebnum); set_random_data(writebuf, pgsize); strcpy(writebuf, "There is no data like this!"); err = mtd_write(mtd, addr0, pgsize, &written, writebuf); if (err || written != pgsize) { - printk(PRINT_PREF "error: write failed at %#llx\n", + pr_err("error: write failed at %#llx\n", (long long)addr0); return err ? err : -1; } - printk(PRINT_PREF "erasing block %d\n", ebnum2); + pr_info("erasing block %d\n", ebnum2); err = erase_eraseblock(ebnum2); if (err) return err; - printk(PRINT_PREF "reading 1st page of block %d\n", ebnum); + pr_info("reading 1st page of block %d\n", ebnum); memset(readbuf, 0, pgsize); err = mtd_read(mtd, addr0, pgsize, &read, readbuf); if (mtd_is_bitflip(err)) err = 0; if (err || read != pgsize) { - printk(PRINT_PREF "error: read failed at %#llx\n", + pr_err("error: read failed at %#llx\n", (long long)addr0); return err ? err : -1; } - printk(PRINT_PREF "verifying 1st page of block %d\n", ebnum); + pr_info("verifying 1st page of block %d\n", ebnum); if (memcmp(writebuf, readbuf, pgsize)) { - printk(PRINT_PREF "verify failed!\n"); + pr_err("verify failed!\n"); errcnt += 1; return -1; } if (!err) - printk(PRINT_PREF "erasecrosstest ok\n"); + pr_info("erasecrosstest ok\n"); return err; } @@ -402,7 +402,7 @@ static int erasetest(void) int err = 0, i, ebnum, ok = 1; loff_t addr0; - printk(PRINT_PREF "erasetest\n"); + pr_info("erasetest\n"); ebnum = 0; addr0 = 0; @@ -411,40 +411,40 @@ static int erasetest(void) ebnum += 1; } - printk(PRINT_PREF "erasing block %d\n", ebnum); + pr_info("erasing block %d\n", ebnum); err = erase_eraseblock(ebnum); if (err) return err; - printk(PRINT_PREF "writing 1st page of block %d\n", ebnum); + pr_info("writing 1st page of block %d\n", ebnum); set_random_data(writebuf, pgsize); err = mtd_write(mtd, addr0, pgsize, &written, writebuf); if (err || written != pgsize) { - printk(PRINT_PREF "error: write failed at %#llx\n", + pr_err("error: write failed at %#llx\n", (long long)addr0); return err ? err : -1; } - printk(PRINT_PREF "erasing block %d\n", ebnum); + pr_info("erasing block %d\n", ebnum); err = erase_eraseblock(ebnum); if (err) return err; - printk(PRINT_PREF "reading 1st page of block %d\n", ebnum); + pr_info("reading 1st page of block %d\n", ebnum); err = mtd_read(mtd, addr0, pgsize, &read, twopages); if (mtd_is_bitflip(err)) err = 0; if (err || read != pgsize) { - printk(PRINT_PREF "error: read failed at %#llx\n", + pr_err("error: read failed at %#llx\n", (long long)addr0); return err ? err : -1; } - printk(PRINT_PREF "verifying 1st page of block %d is all 0xff\n", + pr_info("verifying 1st page of block %d is all 0xff\n", ebnum); for (i = 0; i < pgsize; ++i) if (twopages[i] != 0xff) { - printk(PRINT_PREF "verifying all 0xff failed at %d\n", + pr_err("verifying all 0xff failed at %d\n", i); errcnt += 1; ok = 0; @@ -452,7 +452,7 @@ static int erasetest(void) } if (ok && !err) - printk(PRINT_PREF "erasetest ok\n"); + pr_info("erasetest ok\n"); return err; } @@ -464,7 +464,7 @@ static int is_block_bad(int ebnum) ret = mtd_block_isbad(mtd, addr); if (ret) - printk(PRINT_PREF "block %d is bad\n", ebnum); + pr_info("block %d is bad\n", ebnum); return ret; } @@ -474,18 +474,18 @@ static int scan_for_bad_eraseblocks(void) bbt = kzalloc(ebcnt, GFP_KERNEL); if (!bbt) { - printk(PRINT_PREF "error: cannot allocate memory\n"); + pr_err("error: cannot allocate memory\n"); return -ENOMEM; } - printk(PRINT_PREF "scanning for bad eraseblocks\n"); + pr_info("scanning for bad eraseblocks\n"); for (i = 0; i < ebcnt; ++i) { bbt[i] = is_block_bad(i) ? 1 : 0; if (bbt[i]) bad += 1; cond_resched(); } - printk(PRINT_PREF "scanned %d eraseblocks, %d are bad\n", i, bad); + pr_info("scanned %d eraseblocks, %d are bad\n", i, bad); return 0; } @@ -499,22 +499,22 @@ static int __init mtd_pagetest_init(void) printk(KERN_INFO "=================================================\n"); if (dev < 0) { - printk(PRINT_PREF "Please specify a valid mtd-device via module paramter\n"); - printk(KERN_CRIT "CAREFUL: This test wipes all data on the specified MTD device!\n"); + pr_info("Please specify a valid mtd-device via module parameter\n"); + pr_crit("CAREFUL: This test wipes all data on the specified MTD device!\n"); return -EINVAL; } - printk(PRINT_PREF "MTD device: %d\n", dev); + pr_info("MTD device: %d\n", dev); mtd = get_mtd_device(NULL, dev); if (IS_ERR(mtd)) { err = PTR_ERR(mtd); - printk(PRINT_PREF "error: cannot get MTD device\n"); + pr_err("error: cannot get MTD device\n"); return err; } if (mtd->type != MTD_NANDFLASH) { - printk(PRINT_PREF "this test requires NAND flash\n"); + pr_info("this test requires NAND flash\n"); goto out; } @@ -524,7 +524,7 @@ static int __init mtd_pagetest_init(void) pgcnt = mtd->erasesize / mtd->writesize; pgsize = mtd->writesize; - printk(PRINT_PREF "MTD device size %llu, eraseblock size %u, " + pr_info("MTD device size %llu, eraseblock size %u, " "page size %u, count of eraseblocks %u, pages per " "eraseblock %u, OOB size %u\n", (unsigned long long)mtd->size, mtd->erasesize, @@ -534,17 +534,17 @@ static int __init mtd_pagetest_init(void) bufsize = pgsize * 2; writebuf = kmalloc(mtd->erasesize, GFP_KERNEL); if (!writebuf) { - printk(PRINT_PREF "error: cannot allocate memory\n"); + pr_err("error: cannot allocate memory\n"); goto out; } twopages = kmalloc(bufsize, GFP_KERNEL); if (!twopages) { - printk(PRINT_PREF "error: cannot allocate memory\n"); + pr_err("error: cannot allocate memory\n"); goto out; } boundary = kmalloc(bufsize, GFP_KERNEL); if (!boundary) { - printk(PRINT_PREF "error: cannot allocate memory\n"); + pr_err("error: cannot allocate memory\n"); goto out; } @@ -553,7 +553,7 @@ static int __init mtd_pagetest_init(void) goto out; /* Erase all eraseblocks */ - printk(PRINT_PREF "erasing whole device\n"); + pr_info("erasing whole device\n"); for (i = 0; i < ebcnt; ++i) { if (bbt[i]) continue; @@ -562,11 +562,11 @@ static int __init mtd_pagetest_init(void) goto out; cond_resched(); } - printk(PRINT_PREF "erased %u eraseblocks\n", i); + pr_info("erased %u eraseblocks\n", i); /* Write all eraseblocks */ simple_srand(1); - printk(PRINT_PREF "writing whole device\n"); + pr_info("writing whole device\n"); for (i = 0; i < ebcnt; ++i) { if (bbt[i]) continue; @@ -574,14 +574,14 @@ static int __init mtd_pagetest_init(void) if (err) goto out; if (i % 256 == 0) - printk(PRINT_PREF "written up to eraseblock %u\n", i); + pr_info("written up to eraseblock %u\n", i); cond_resched(); } - printk(PRINT_PREF "written %u eraseblocks\n", i); + pr_info("written %u eraseblocks\n", i); /* Check all eraseblocks */ simple_srand(1); - printk(PRINT_PREF "verifying all eraseblocks\n"); + pr_info("verifying all eraseblocks\n"); for (i = 0; i < ebcnt; ++i) { if (bbt[i]) continue; @@ -589,10 +589,10 @@ static int __init mtd_pagetest_init(void) if (err) goto out; if (i % 256 == 0) - printk(PRINT_PREF "verified up to eraseblock %u\n", i); + pr_info("verified up to eraseblock %u\n", i); cond_resched(); } - printk(PRINT_PREF "verified %u eraseblocks\n", i); + pr_info("verified %u eraseblocks\n", i); err = crosstest(); if (err) @@ -606,7 +606,7 @@ static int __init mtd_pagetest_init(void) if (err) goto out; - printk(PRINT_PREF "finished with %d errors\n", errcnt); + pr_info("finished with %d errors\n", errcnt); out: kfree(bbt); @@ -615,7 +615,7 @@ out: kfree(writebuf); put_mtd_device(mtd); if (err) - printk(PRINT_PREF "error %d occurred\n", err); + pr_info("error %d occurred\n", err); printk(KERN_INFO "=================================================\n"); return err; } diff --git a/drivers/mtd/tests/mtd_readtest.c b/drivers/mtd/tests/mtd_readtest.c index 121aba189cec..266de04b6d29 100644 --- a/drivers/mtd/tests/mtd_readtest.c +++ b/drivers/mtd/tests/mtd_readtest.c @@ -19,6 +19,8 @@ * Author: Adrian Hunter <ext-adrian.hunter@nokia.com> */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/init.h> #include <linux/module.h> #include <linux/moduleparam.h> @@ -27,8 +29,6 @@ #include <linux/slab.h> #include <linux/sched.h> -#define PRINT_PREF KERN_INFO "mtd_readtest: " - static int dev = -EINVAL; module_param(dev, int, S_IRUGO); MODULE_PARM_DESC(dev, "MTD device number to use"); @@ -51,12 +51,12 @@ static int read_eraseblock_by_page(int ebnum) void *oobbuf = iobuf1; for (i = 0; i < pgcnt; i++) { - memset(buf, 0 , pgcnt); + memset(buf, 0 , pgsize); ret = mtd_read(mtd, addr, pgsize, &read, buf); if (ret == -EUCLEAN) ret = 0; if (ret || read != pgsize) { - printk(PRINT_PREF "error: read failed at %#llx\n", + pr_err("error: read failed at %#llx\n", (long long)addr); if (!err) err = ret; @@ -77,7 +77,7 @@ static int read_eraseblock_by_page(int ebnum) ret = mtd_read_oob(mtd, addr, &ops); if ((ret && !mtd_is_bitflip(ret)) || ops.oobretlen != mtd->oobsize) { - printk(PRINT_PREF "error: read oob failed at " + pr_err("error: read oob failed at " "%#llx\n", (long long)addr); if (!err) err = ret; @@ -99,7 +99,7 @@ static void dump_eraseblock(int ebnum) char line[128]; int pg, oob; - printk(PRINT_PREF "dumping eraseblock %d\n", ebnum); + pr_info("dumping eraseblock %d\n", ebnum); n = mtd->erasesize; for (i = 0; i < n;) { char *p = line; @@ -112,7 +112,7 @@ static void dump_eraseblock(int ebnum) } if (!mtd->oobsize) return; - printk(PRINT_PREF "dumping oob from eraseblock %d\n", ebnum); + pr_info("dumping oob from eraseblock %d\n", ebnum); n = mtd->oobsize; for (pg = 0, i = 0; pg < pgcnt; pg++) for (oob = 0; oob < n;) { @@ -134,7 +134,7 @@ static int is_block_bad(int ebnum) ret = mtd_block_isbad(mtd, addr); if (ret) - printk(PRINT_PREF "block %d is bad\n", ebnum); + pr_info("block %d is bad\n", ebnum); return ret; } @@ -144,21 +144,21 @@ static int scan_for_bad_eraseblocks(void) bbt = kzalloc(ebcnt, GFP_KERNEL); if (!bbt) { - printk(PRINT_PREF "error: cannot allocate memory\n"); + pr_err("error: cannot allocate memory\n"); return -ENOMEM; } if (!mtd_can_have_bb(mtd)) return 0; - printk(PRINT_PREF "scanning for bad eraseblocks\n"); + pr_info("scanning for bad eraseblocks\n"); for (i = 0; i < ebcnt; ++i) { bbt[i] = is_block_bad(i) ? 1 : 0; if (bbt[i]) bad += 1; cond_resched(); } - printk(PRINT_PREF "scanned %d eraseblocks, %d are bad\n", i, bad); + pr_info("scanned %d eraseblocks, %d are bad\n", i, bad); return 0; } @@ -171,21 +171,21 @@ static int __init mtd_readtest_init(void) printk(KERN_INFO "=================================================\n"); if (dev < 0) { - printk(PRINT_PREF "Please specify a valid mtd-device via module paramter\n"); + pr_info("Please specify a valid mtd-device via module parameter\n"); return -EINVAL; } - printk(PRINT_PREF "MTD device: %d\n", dev); + pr_info("MTD device: %d\n", dev); mtd = get_mtd_device(NULL, dev); if (IS_ERR(mtd)) { err = PTR_ERR(mtd); - printk(PRINT_PREF "error: Cannot get MTD device\n"); + pr_err("error: Cannot get MTD device\n"); return err; } if (mtd->writesize == 1) { - printk(PRINT_PREF "not NAND flash, assume page size is 512 " + pr_info("not NAND flash, assume page size is 512 " "bytes.\n"); pgsize = 512; } else @@ -196,7 +196,7 @@ static int __init mtd_readtest_init(void) ebcnt = tmp; pgcnt = mtd->erasesize / pgsize; - printk(PRINT_PREF "MTD device size %llu, eraseblock size %u, " + pr_info("MTD device size %llu, eraseblock size %u, " "page size %u, count of eraseblocks %u, pages per " "eraseblock %u, OOB size %u\n", (unsigned long long)mtd->size, mtd->erasesize, @@ -205,12 +205,12 @@ static int __init mtd_readtest_init(void) err = -ENOMEM; iobuf = kmalloc(mtd->erasesize, GFP_KERNEL); if (!iobuf) { - printk(PRINT_PREF "error: cannot allocate memory\n"); + pr_err("error: cannot allocate memory\n"); goto out; } iobuf1 = kmalloc(mtd->erasesize, GFP_KERNEL); if (!iobuf1) { - printk(PRINT_PREF "error: cannot allocate memory\n"); + pr_err("error: cannot allocate memory\n"); goto out; } @@ -219,7 +219,7 @@ static int __init mtd_readtest_init(void) goto out; /* Read all eraseblocks 1 page at a time */ - printk(PRINT_PREF "testing page read\n"); + pr_info("testing page read\n"); for (i = 0; i < ebcnt; ++i) { int ret; @@ -235,9 +235,9 @@ static int __init mtd_readtest_init(void) } if (err) - printk(PRINT_PREF "finished with errors\n"); + pr_info("finished with errors\n"); else - printk(PRINT_PREF "finished\n"); + pr_info("finished\n"); out: @@ -246,7 +246,7 @@ out: kfree(bbt); put_mtd_device(mtd); if (err) - printk(PRINT_PREF "error %d occurred\n", err); + pr_info("error %d occurred\n", err); printk(KERN_INFO "=================================================\n"); return err; } diff --git a/drivers/mtd/tests/mtd_speedtest.c b/drivers/mtd/tests/mtd_speedtest.c index 42b0f7456fc4..596cbea8df4c 100644 --- a/drivers/mtd/tests/mtd_speedtest.c +++ b/drivers/mtd/tests/mtd_speedtest.c @@ -19,6 +19,8 @@ * Author: Adrian Hunter <adrian.hunter@nokia.com> */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/init.h> #include <linux/module.h> #include <linux/moduleparam.h> @@ -28,8 +30,6 @@ #include <linux/sched.h> #include <linux/random.h> -#define PRINT_PREF KERN_INFO "mtd_speedtest: " - static int dev = -EINVAL; module_param(dev, int, S_IRUGO); MODULE_PARM_DESC(dev, "MTD device number to use"); @@ -70,12 +70,12 @@ static int erase_eraseblock(int ebnum) err = mtd_erase(mtd, &ei); if (err) { - printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum); + pr_err("error %d while erasing EB %d\n", err, ebnum); return err; } if (ei.state == MTD_ERASE_FAILED) { - printk(PRINT_PREF "some erase error occurred at EB %d\n", + pr_err("some erase error occurred at EB %d\n", ebnum); return -EIO; } @@ -96,13 +96,13 @@ static int multiblock_erase(int ebnum, int blocks) err = mtd_erase(mtd, &ei); if (err) { - printk(PRINT_PREF "error %d while erasing EB %d, blocks %d\n", + pr_err("error %d while erasing EB %d, blocks %d\n", err, ebnum, blocks); return err; } if (ei.state == MTD_ERASE_FAILED) { - printk(PRINT_PREF "some erase error occurred at EB %d," + pr_err("some erase error occurred at EB %d," "blocks %d\n", ebnum, blocks); return -EIO; } @@ -134,7 +134,7 @@ static int write_eraseblock(int ebnum) err = mtd_write(mtd, addr, mtd->erasesize, &written, iobuf); if (err || written != mtd->erasesize) { - printk(PRINT_PREF "error: write failed at %#llx\n", addr); + pr_err("error: write failed at %#llx\n", addr); if (!err) err = -EINVAL; } @@ -152,7 +152,7 @@ static int write_eraseblock_by_page(int ebnum) for (i = 0; i < pgcnt; i++) { err = mtd_write(mtd, addr, pgsize, &written, buf); if (err || written != pgsize) { - printk(PRINT_PREF "error: write failed at %#llx\n", + pr_err("error: write failed at %#llx\n", addr); if (!err) err = -EINVAL; @@ -175,7 +175,7 @@ static int write_eraseblock_by_2pages(int ebnum) for (i = 0; i < n; i++) { err = mtd_write(mtd, addr, sz, &written, buf); if (err || written != sz) { - printk(PRINT_PREF "error: write failed at %#llx\n", + pr_err("error: write failed at %#llx\n", addr); if (!err) err = -EINVAL; @@ -187,7 +187,7 @@ static int write_eraseblock_by_2pages(int ebnum) if (pgcnt % 2) { err = mtd_write(mtd, addr, pgsize, &written, buf); if (err || written != pgsize) { - printk(PRINT_PREF "error: write failed at %#llx\n", + pr_err("error: write failed at %#llx\n", addr); if (!err) err = -EINVAL; @@ -208,7 +208,7 @@ static int read_eraseblock(int ebnum) if (mtd_is_bitflip(err)) err = 0; if (err || read != mtd->erasesize) { - printk(PRINT_PREF "error: read failed at %#llx\n", addr); + pr_err("error: read failed at %#llx\n", addr); if (!err) err = -EINVAL; } @@ -229,7 +229,7 @@ static int read_eraseblock_by_page(int ebnum) if (mtd_is_bitflip(err)) err = 0; if (err || read != pgsize) { - printk(PRINT_PREF "error: read failed at %#llx\n", + pr_err("error: read failed at %#llx\n", addr); if (!err) err = -EINVAL; @@ -255,7 +255,7 @@ static int read_eraseblock_by_2pages(int ebnum) if (mtd_is_bitflip(err)) err = 0; if (err || read != sz) { - printk(PRINT_PREF "error: read failed at %#llx\n", + pr_err("error: read failed at %#llx\n", addr); if (!err) err = -EINVAL; @@ -270,7 +270,7 @@ static int read_eraseblock_by_2pages(int ebnum) if (mtd_is_bitflip(err)) err = 0; if (err || read != pgsize) { - printk(PRINT_PREF "error: read failed at %#llx\n", + pr_err("error: read failed at %#llx\n", addr); if (!err) err = -EINVAL; @@ -287,7 +287,7 @@ static int is_block_bad(int ebnum) ret = mtd_block_isbad(mtd, addr); if (ret) - printk(PRINT_PREF "block %d is bad\n", ebnum); + pr_info("block %d is bad\n", ebnum); return ret; } @@ -321,21 +321,21 @@ static int scan_for_bad_eraseblocks(void) bbt = kzalloc(ebcnt, GFP_KERNEL); if (!bbt) { - printk(PRINT_PREF "error: cannot allocate memory\n"); + pr_err("error: cannot allocate memory\n"); return -ENOMEM; } if (!mtd_can_have_bb(mtd)) goto out; - printk(PRINT_PREF "scanning for bad eraseblocks\n"); + pr_info("scanning for bad eraseblocks\n"); for (i = 0; i < ebcnt; ++i) { bbt[i] = is_block_bad(i) ? 1 : 0; if (bbt[i]) bad += 1; cond_resched(); } - printk(PRINT_PREF "scanned %d eraseblocks, %d are bad\n", i, bad); + pr_info("scanned %d eraseblocks, %d are bad\n", i, bad); out: goodebcnt = ebcnt - bad; return 0; @@ -351,25 +351,25 @@ static int __init mtd_speedtest_init(void) printk(KERN_INFO "=================================================\n"); if (dev < 0) { - printk(PRINT_PREF "Please specify a valid mtd-device via module paramter\n"); - printk(KERN_CRIT "CAREFUL: This test wipes all data on the specified MTD device!\n"); + pr_info("Please specify a valid mtd-device via module parameter\n"); + pr_crit("CAREFUL: This test wipes all data on the specified MTD device!\n"); return -EINVAL; } if (count) - printk(PRINT_PREF "MTD device: %d count: %d\n", dev, count); + pr_info("MTD device: %d count: %d\n", dev, count); else - printk(PRINT_PREF "MTD device: %d\n", dev); + pr_info("MTD device: %d\n", dev); mtd = get_mtd_device(NULL, dev); if (IS_ERR(mtd)) { err = PTR_ERR(mtd); - printk(PRINT_PREF "error: cannot get MTD device\n"); + pr_err("error: cannot get MTD device\n"); return err; } if (mtd->writesize == 1) { - printk(PRINT_PREF "not NAND flash, assume page size is 512 " + pr_info("not NAND flash, assume page size is 512 " "bytes.\n"); pgsize = 512; } else @@ -380,7 +380,7 @@ static int __init mtd_speedtest_init(void) ebcnt = tmp; pgcnt = mtd->erasesize / pgsize; - printk(PRINT_PREF "MTD device size %llu, eraseblock size %u, " + pr_info("MTD device size %llu, eraseblock size %u, " "page size %u, count of eraseblocks %u, pages per " "eraseblock %u, OOB size %u\n", (unsigned long long)mtd->size, mtd->erasesize, @@ -392,7 +392,7 @@ static int __init mtd_speedtest_init(void) err = -ENOMEM; iobuf = kmalloc(mtd->erasesize, GFP_KERNEL); if (!iobuf) { - printk(PRINT_PREF "error: cannot allocate memory\n"); + pr_err("error: cannot allocate memory\n"); goto out; } @@ -407,7 +407,7 @@ static int __init mtd_speedtest_init(void) goto out; /* Write all eraseblocks, 1 eraseblock at a time */ - printk(PRINT_PREF "testing eraseblock write speed\n"); + pr_info("testing eraseblock write speed\n"); start_timing(); for (i = 0; i < ebcnt; ++i) { if (bbt[i]) @@ -419,10 +419,10 @@ static int __init mtd_speedtest_init(void) } stop_timing(); speed = calc_speed(); - printk(PRINT_PREF "eraseblock write speed is %ld KiB/s\n", speed); + pr_info("eraseblock write speed is %ld KiB/s\n", speed); /* Read all eraseblocks, 1 eraseblock at a time */ - printk(PRINT_PREF "testing eraseblock read speed\n"); + pr_info("testing eraseblock read speed\n"); start_timing(); for (i = 0; i < ebcnt; ++i) { if (bbt[i]) @@ -434,14 +434,14 @@ static int __init mtd_speedtest_init(void) } stop_timing(); speed = calc_speed(); - printk(PRINT_PREF "eraseblock read speed is %ld KiB/s\n", speed); + pr_info("eraseblock read speed is %ld KiB/s\n", speed); err = erase_whole_device(); if (err) goto out; /* Write all eraseblocks, 1 page at a time */ - printk(PRINT_PREF "testing page write speed\n"); + pr_info("testing page write speed\n"); start_timing(); for (i = 0; i < ebcnt; ++i) { if (bbt[i]) @@ -453,10 +453,10 @@ static int __init mtd_speedtest_init(void) } stop_timing(); speed = calc_speed(); - printk(PRINT_PREF "page write speed is %ld KiB/s\n", speed); + pr_info("page write speed is %ld KiB/s\n", speed); /* Read all eraseblocks, 1 page at a time */ - printk(PRINT_PREF "testing page read speed\n"); + pr_info("testing page read speed\n"); start_timing(); for (i = 0; i < ebcnt; ++i) { if (bbt[i]) @@ -468,14 +468,14 @@ static int __init mtd_speedtest_init(void) } stop_timing(); speed = calc_speed(); - printk(PRINT_PREF "page read speed is %ld KiB/s\n", speed); + pr_info("page read speed is %ld KiB/s\n", speed); err = erase_whole_device(); if (err) goto out; /* Write all eraseblocks, 2 pages at a time */ - printk(PRINT_PREF "testing 2 page write speed\n"); + pr_info("testing 2 page write speed\n"); start_timing(); for (i = 0; i < ebcnt; ++i) { if (bbt[i]) @@ -487,10 +487,10 @@ static int __init mtd_speedtest_init(void) } stop_timing(); speed = calc_speed(); - printk(PRINT_PREF "2 page write speed is %ld KiB/s\n", speed); + pr_info("2 page write speed is %ld KiB/s\n", speed); /* Read all eraseblocks, 2 pages at a time */ - printk(PRINT_PREF "testing 2 page read speed\n"); + pr_info("testing 2 page read speed\n"); start_timing(); for (i = 0; i < ebcnt; ++i) { if (bbt[i]) @@ -502,10 +502,10 @@ static int __init mtd_speedtest_init(void) } stop_timing(); speed = calc_speed(); - printk(PRINT_PREF "2 page read speed is %ld KiB/s\n", speed); + pr_info("2 page read speed is %ld KiB/s\n", speed); /* Erase all eraseblocks */ - printk(PRINT_PREF "Testing erase speed\n"); + pr_info("Testing erase speed\n"); start_timing(); for (i = 0; i < ebcnt; ++i) { if (bbt[i]) @@ -517,12 +517,12 @@ static int __init mtd_speedtest_init(void) } stop_timing(); speed = calc_speed(); - printk(PRINT_PREF "erase speed is %ld KiB/s\n", speed); + pr_info("erase speed is %ld KiB/s\n", speed); /* Multi-block erase all eraseblocks */ for (k = 1; k < 7; k++) { blocks = 1 << k; - printk(PRINT_PREF "Testing %dx multi-block erase speed\n", + pr_info("Testing %dx multi-block erase speed\n", blocks); start_timing(); for (i = 0; i < ebcnt; ) { @@ -541,16 +541,16 @@ static int __init mtd_speedtest_init(void) } stop_timing(); speed = calc_speed(); - printk(PRINT_PREF "%dx multi-block erase speed is %ld KiB/s\n", + pr_info("%dx multi-block erase speed is %ld KiB/s\n", blocks, speed); } - printk(PRINT_PREF "finished\n"); + pr_info("finished\n"); out: kfree(iobuf); kfree(bbt); put_mtd_device(mtd); if (err) - printk(PRINT_PREF "error %d occurred\n", err); + pr_info("error %d occurred\n", err); printk(KERN_INFO "=================================================\n"); return err; } diff --git a/drivers/mtd/tests/mtd_stresstest.c b/drivers/mtd/tests/mtd_stresstest.c index cb268cebf01a..3729f679ae5d 100644 --- a/drivers/mtd/tests/mtd_stresstest.c +++ b/drivers/mtd/tests/mtd_stresstest.c @@ -19,6 +19,8 @@ * Author: Adrian Hunter <ext-adrian.hunter@nokia.com> */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/init.h> #include <linux/module.h> #include <linux/moduleparam.h> @@ -29,8 +31,6 @@ #include <linux/vmalloc.h> #include <linux/random.h> -#define PRINT_PREF KERN_INFO "mtd_stresstest: " - static int dev = -EINVAL; module_param(dev, int, S_IRUGO); MODULE_PARM_DESC(dev, "MTD device number to use"); @@ -94,12 +94,12 @@ static int erase_eraseblock(int ebnum) err = mtd_erase(mtd, &ei); if (unlikely(err)) { - printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum); + pr_err("error %d while erasing EB %d\n", err, ebnum); return err; } if (unlikely(ei.state == MTD_ERASE_FAILED)) { - printk(PRINT_PREF "some erase error occurred at EB %d\n", + pr_err("some erase error occurred at EB %d\n", ebnum); return -EIO; } @@ -114,7 +114,7 @@ static int is_block_bad(int ebnum) ret = mtd_block_isbad(mtd, addr); if (ret) - printk(PRINT_PREF "block %d is bad\n", ebnum); + pr_info("block %d is bad\n", ebnum); return ret; } @@ -137,7 +137,7 @@ static int do_read(void) if (mtd_is_bitflip(err)) err = 0; if (unlikely(err || read != len)) { - printk(PRINT_PREF "error: read failed at 0x%llx\n", + pr_err("error: read failed at 0x%llx\n", (long long)addr); if (!err) err = -EINVAL; @@ -174,7 +174,7 @@ static int do_write(void) addr = eb * mtd->erasesize + offs; err = mtd_write(mtd, addr, len, &written, writebuf); if (unlikely(err || written != len)) { - printk(PRINT_PREF "error: write failed at 0x%llx\n", + pr_err("error: write failed at 0x%llx\n", (long long)addr); if (!err) err = -EINVAL; @@ -203,21 +203,21 @@ static int scan_for_bad_eraseblocks(void) bbt = kzalloc(ebcnt, GFP_KERNEL); if (!bbt) { - printk(PRINT_PREF "error: cannot allocate memory\n"); + pr_err("error: cannot allocate memory\n"); return -ENOMEM; } if (!mtd_can_have_bb(mtd)) return 0; - printk(PRINT_PREF "scanning for bad eraseblocks\n"); + pr_info("scanning for bad eraseblocks\n"); for (i = 0; i < ebcnt; ++i) { bbt[i] = is_block_bad(i) ? 1 : 0; if (bbt[i]) bad += 1; cond_resched(); } - printk(PRINT_PREF "scanned %d eraseblocks, %d are bad\n", i, bad); + pr_info("scanned %d eraseblocks, %d are bad\n", i, bad); return 0; } @@ -231,22 +231,22 @@ static int __init mtd_stresstest_init(void) printk(KERN_INFO "=================================================\n"); if (dev < 0) { - printk(PRINT_PREF "Please specify a valid mtd-device via module paramter\n"); - printk(KERN_CRIT "CAREFUL: This test wipes all data on the specified MTD device!\n"); + pr_info("Please specify a valid mtd-device via module parameter\n"); + pr_crit("CAREFUL: This test wipes all data on the specified MTD device!\n"); return -EINVAL; } - printk(PRINT_PREF "MTD device: %d\n", dev); + pr_info("MTD device: %d\n", dev); mtd = get_mtd_device(NULL, dev); if (IS_ERR(mtd)) { err = PTR_ERR(mtd); - printk(PRINT_PREF "error: cannot get MTD device\n"); + pr_err("error: cannot get MTD device\n"); return err; } if (mtd->writesize == 1) { - printk(PRINT_PREF "not NAND flash, assume page size is 512 " + pr_info("not NAND flash, assume page size is 512 " "bytes.\n"); pgsize = 512; } else @@ -257,14 +257,14 @@ static int __init mtd_stresstest_init(void) ebcnt = tmp; pgcnt = mtd->erasesize / pgsize; - printk(PRINT_PREF "MTD device size %llu, eraseblock size %u, " + pr_info("MTD device size %llu, eraseblock size %u, " "page size %u, count of eraseblocks %u, pages per " "eraseblock %u, OOB size %u\n", (unsigned long long)mtd->size, mtd->erasesize, pgsize, ebcnt, pgcnt, mtd->oobsize); if (ebcnt < 2) { - printk(PRINT_PREF "error: need at least 2 eraseblocks\n"); + pr_err("error: need at least 2 eraseblocks\n"); err = -ENOSPC; goto out_put_mtd; } @@ -277,7 +277,7 @@ static int __init mtd_stresstest_init(void) writebuf = vmalloc(bufsize); offsets = kmalloc(ebcnt * sizeof(int), GFP_KERNEL); if (!readbuf || !writebuf || !offsets) { - printk(PRINT_PREF "error: cannot allocate memory\n"); + pr_err("error: cannot allocate memory\n"); goto out; } for (i = 0; i < ebcnt; i++) @@ -290,16 +290,16 @@ static int __init mtd_stresstest_init(void) goto out; /* Do operations */ - printk(PRINT_PREF "doing operations\n"); + pr_info("doing operations\n"); for (op = 0; op < count; op++) { if ((op & 1023) == 0) - printk(PRINT_PREF "%d operations done\n", op); + pr_info("%d operations done\n", op); err = do_operation(); if (err) goto out; cond_resched(); } - printk(PRINT_PREF "finished, %d operations done\n", op); + pr_info("finished, %d operations done\n", op); out: kfree(offsets); @@ -309,7 +309,7 @@ out: out_put_mtd: put_mtd_device(mtd); if (err) - printk(PRINT_PREF "error %d occurred\n", err); + pr_info("error %d occurred\n", err); printk(KERN_INFO "=================================================\n"); return err; } diff --git a/drivers/mtd/tests/mtd_subpagetest.c b/drivers/mtd/tests/mtd_subpagetest.c index 9667bf535282..c880c2229c59 100644 --- a/drivers/mtd/tests/mtd_subpagetest.c +++ b/drivers/mtd/tests/mtd_subpagetest.c @@ -19,6 +19,8 @@ * */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/init.h> #include <linux/module.h> #include <linux/moduleparam.h> @@ -27,8 +29,6 @@ #include <linux/slab.h> #include <linux/sched.h> -#define PRINT_PREF KERN_INFO "mtd_subpagetest: " - static int dev = -EINVAL; module_param(dev, int, S_IRUGO); MODULE_PARM_DESC(dev, "MTD device number to use"); @@ -82,12 +82,12 @@ static int erase_eraseblock(int ebnum) err = mtd_erase(mtd, &ei); if (err) { - printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum); + pr_err("error %d while erasing EB %d\n", err, ebnum); return err; } if (ei.state == MTD_ERASE_FAILED) { - printk(PRINT_PREF "some erase error occurred at EB %d\n", + pr_err("some erase error occurred at EB %d\n", ebnum); return -EIO; } @@ -100,7 +100,7 @@ static int erase_whole_device(void) int err; unsigned int i; - printk(PRINT_PREF "erasing whole device\n"); + pr_info("erasing whole device\n"); for (i = 0; i < ebcnt; ++i) { if (bbt[i]) continue; @@ -109,7 +109,7 @@ static int erase_whole_device(void) return err; cond_resched(); } - printk(PRINT_PREF "erased %u eraseblocks\n", i); + pr_info("erased %u eraseblocks\n", i); return 0; } @@ -122,11 +122,11 @@ static int write_eraseblock(int ebnum) set_random_data(writebuf, subpgsize); err = mtd_write(mtd, addr, subpgsize, &written, writebuf); if (unlikely(err || written != subpgsize)) { - printk(PRINT_PREF "error: write failed at %#llx\n", + pr_err("error: write failed at %#llx\n", (long long)addr); if (written != subpgsize) { - printk(PRINT_PREF " write size: %#x\n", subpgsize); - printk(PRINT_PREF " written: %#zx\n", written); + pr_err(" write size: %#x\n", subpgsize); + pr_err(" written: %#zx\n", written); } return err ? err : -1; } @@ -136,11 +136,11 @@ static int write_eraseblock(int ebnum) set_random_data(writebuf, subpgsize); err = mtd_write(mtd, addr, subpgsize, &written, writebuf); if (unlikely(err || written != subpgsize)) { - printk(PRINT_PREF "error: write failed at %#llx\n", + pr_err("error: write failed at %#llx\n", (long long)addr); if (written != subpgsize) { - printk(PRINT_PREF " write size: %#x\n", subpgsize); - printk(PRINT_PREF " written: %#zx\n", written); + pr_err(" write size: %#x\n", subpgsize); + pr_err(" written: %#zx\n", written); } return err ? err : -1; } @@ -160,12 +160,12 @@ static int write_eraseblock2(int ebnum) set_random_data(writebuf, subpgsize * k); err = mtd_write(mtd, addr, subpgsize * k, &written, writebuf); if (unlikely(err || written != subpgsize * k)) { - printk(PRINT_PREF "error: write failed at %#llx\n", + pr_err("error: write failed at %#llx\n", (long long)addr); if (written != subpgsize) { - printk(PRINT_PREF " write size: %#x\n", + pr_err(" write size: %#x\n", subpgsize * k); - printk(PRINT_PREF " written: %#08zx\n", + pr_err(" written: %#08zx\n", written); } return err ? err : -1; @@ -198,23 +198,23 @@ static int verify_eraseblock(int ebnum) err = mtd_read(mtd, addr, subpgsize, &read, readbuf); if (unlikely(err || read != subpgsize)) { if (mtd_is_bitflip(err) && read == subpgsize) { - printk(PRINT_PREF "ECC correction at %#llx\n", + pr_info("ECC correction at %#llx\n", (long long)addr); err = 0; } else { - printk(PRINT_PREF "error: read failed at %#llx\n", + pr_err("error: read failed at %#llx\n", (long long)addr); return err ? err : -1; } } if (unlikely(memcmp(readbuf, writebuf, subpgsize))) { - printk(PRINT_PREF "error: verify failed at %#llx\n", + pr_err("error: verify failed at %#llx\n", (long long)addr); - printk(PRINT_PREF "------------- written----------------\n"); + pr_info("------------- written----------------\n"); print_subpage(writebuf); - printk(PRINT_PREF "------------- read ------------------\n"); + pr_info("------------- read ------------------\n"); print_subpage(readbuf); - printk(PRINT_PREF "-------------------------------------\n"); + pr_info("-------------------------------------\n"); errcnt += 1; } @@ -225,23 +225,23 @@ static int verify_eraseblock(int ebnum) err = mtd_read(mtd, addr, subpgsize, &read, readbuf); if (unlikely(err || read != subpgsize)) { if (mtd_is_bitflip(err) && read == subpgsize) { - printk(PRINT_PREF "ECC correction at %#llx\n", + pr_info("ECC correction at %#llx\n", (long long)addr); err = 0; } else { - printk(PRINT_PREF "error: read failed at %#llx\n", + pr_err("error: read failed at %#llx\n", (long long)addr); return err ? err : -1; } } if (unlikely(memcmp(readbuf, writebuf, subpgsize))) { - printk(PRINT_PREF "error: verify failed at %#llx\n", + pr_info("error: verify failed at %#llx\n", (long long)addr); - printk(PRINT_PREF "------------- written----------------\n"); + pr_info("------------- written----------------\n"); print_subpage(writebuf); - printk(PRINT_PREF "------------- read ------------------\n"); + pr_info("------------- read ------------------\n"); print_subpage(readbuf); - printk(PRINT_PREF "-------------------------------------\n"); + pr_info("-------------------------------------\n"); errcnt += 1; } @@ -262,17 +262,17 @@ static int verify_eraseblock2(int ebnum) err = mtd_read(mtd, addr, subpgsize * k, &read, readbuf); if (unlikely(err || read != subpgsize * k)) { if (mtd_is_bitflip(err) && read == subpgsize * k) { - printk(PRINT_PREF "ECC correction at %#llx\n", + pr_info("ECC correction at %#llx\n", (long long)addr); err = 0; } else { - printk(PRINT_PREF "error: read failed at " + pr_err("error: read failed at " "%#llx\n", (long long)addr); return err ? err : -1; } } if (unlikely(memcmp(readbuf, writebuf, subpgsize * k))) { - printk(PRINT_PREF "error: verify failed at %#llx\n", + pr_err("error: verify failed at %#llx\n", (long long)addr); errcnt += 1; } @@ -295,17 +295,17 @@ static int verify_eraseblock_ff(int ebnum) err = mtd_read(mtd, addr, subpgsize, &read, readbuf); if (unlikely(err || read != subpgsize)) { if (mtd_is_bitflip(err) && read == subpgsize) { - printk(PRINT_PREF "ECC correction at %#llx\n", + pr_info("ECC correction at %#llx\n", (long long)addr); err = 0; } else { - printk(PRINT_PREF "error: read failed at " + pr_err("error: read failed at " "%#llx\n", (long long)addr); return err ? err : -1; } } if (unlikely(memcmp(readbuf, writebuf, subpgsize))) { - printk(PRINT_PREF "error: verify 0xff failed at " + pr_err("error: verify 0xff failed at " "%#llx\n", (long long)addr); errcnt += 1; } @@ -320,7 +320,7 @@ static int verify_all_eraseblocks_ff(void) int err; unsigned int i; - printk(PRINT_PREF "verifying all eraseblocks for 0xff\n"); + pr_info("verifying all eraseblocks for 0xff\n"); for (i = 0; i < ebcnt; ++i) { if (bbt[i]) continue; @@ -328,10 +328,10 @@ static int verify_all_eraseblocks_ff(void) if (err) return err; if (i % 256 == 0) - printk(PRINT_PREF "verified up to eraseblock %u\n", i); + pr_info("verified up to eraseblock %u\n", i); cond_resched(); } - printk(PRINT_PREF "verified %u eraseblocks\n", i); + pr_info("verified %u eraseblocks\n", i); return 0; } @@ -342,7 +342,7 @@ static int is_block_bad(int ebnum) ret = mtd_block_isbad(mtd, addr); if (ret) - printk(PRINT_PREF "block %d is bad\n", ebnum); + pr_info("block %d is bad\n", ebnum); return ret; } @@ -352,18 +352,18 @@ static int scan_for_bad_eraseblocks(void) bbt = kzalloc(ebcnt, GFP_KERNEL); if (!bbt) { - printk(PRINT_PREF "error: cannot allocate memory\n"); + pr_err("error: cannot allocate memory\n"); return -ENOMEM; } - printk(PRINT_PREF "scanning for bad eraseblocks\n"); + pr_info("scanning for bad eraseblocks\n"); for (i = 0; i < ebcnt; ++i) { bbt[i] = is_block_bad(i) ? 1 : 0; if (bbt[i]) bad += 1; cond_resched(); } - printk(PRINT_PREF "scanned %d eraseblocks, %d are bad\n", i, bad); + pr_info("scanned %d eraseblocks, %d are bad\n", i, bad); return 0; } @@ -377,22 +377,22 @@ static int __init mtd_subpagetest_init(void) printk(KERN_INFO "=================================================\n"); if (dev < 0) { - printk(PRINT_PREF "Please specify a valid mtd-device via module paramter\n"); - printk(KERN_CRIT "CAREFUL: This test wipes all data on the specified MTD device!\n"); + pr_info("Please specify a valid mtd-device via module parameter\n"); + pr_crit("CAREFUL: This test wipes all data on the specified MTD device!\n"); return -EINVAL; } - printk(PRINT_PREF "MTD device: %d\n", dev); + pr_info("MTD device: %d\n", dev); mtd = get_mtd_device(NULL, dev); if (IS_ERR(mtd)) { err = PTR_ERR(mtd); - printk(PRINT_PREF "error: cannot get MTD device\n"); + pr_err("error: cannot get MTD device\n"); return err; } if (mtd->type != MTD_NANDFLASH) { - printk(PRINT_PREF "this test requires NAND flash\n"); + pr_info("this test requires NAND flash\n"); goto out; } @@ -402,7 +402,7 @@ static int __init mtd_subpagetest_init(void) ebcnt = tmp; pgcnt = mtd->erasesize / mtd->writesize; - printk(PRINT_PREF "MTD device size %llu, eraseblock size %u, " + pr_info("MTD device size %llu, eraseblock size %u, " "page size %u, subpage size %u, count of eraseblocks %u, " "pages per eraseblock %u, OOB size %u\n", (unsigned long long)mtd->size, mtd->erasesize, @@ -412,12 +412,12 @@ static int __init mtd_subpagetest_init(void) bufsize = subpgsize * 32; writebuf = kmalloc(bufsize, GFP_KERNEL); if (!writebuf) { - printk(PRINT_PREF "error: cannot allocate memory\n"); + pr_info("error: cannot allocate memory\n"); goto out; } readbuf = kmalloc(bufsize, GFP_KERNEL); if (!readbuf) { - printk(PRINT_PREF "error: cannot allocate memory\n"); + pr_info("error: cannot allocate memory\n"); goto out; } @@ -429,7 +429,7 @@ static int __init mtd_subpagetest_init(void) if (err) goto out; - printk(PRINT_PREF "writing whole device\n"); + pr_info("writing whole device\n"); simple_srand(1); for (i = 0; i < ebcnt; ++i) { if (bbt[i]) @@ -438,13 +438,13 @@ static int __init mtd_subpagetest_init(void) if (unlikely(err)) goto out; if (i % 256 == 0) - printk(PRINT_PREF "written up to eraseblock %u\n", i); + pr_info("written up to eraseblock %u\n", i); cond_resched(); } - printk(PRINT_PREF "written %u eraseblocks\n", i); + pr_info("written %u eraseblocks\n", i); simple_srand(1); - printk(PRINT_PREF "verifying all eraseblocks\n"); + pr_info("verifying all eraseblocks\n"); for (i = 0; i < ebcnt; ++i) { if (bbt[i]) continue; @@ -452,10 +452,10 @@ static int __init mtd_subpagetest_init(void) if (unlikely(err)) goto out; if (i % 256 == 0) - printk(PRINT_PREF "verified up to eraseblock %u\n", i); + pr_info("verified up to eraseblock %u\n", i); cond_resched(); } - printk(PRINT_PREF "verified %u eraseblocks\n", i); + pr_info("verified %u eraseblocks\n", i); err = erase_whole_device(); if (err) @@ -467,7 +467,7 @@ static int __init mtd_subpagetest_init(void) /* Write all eraseblocks */ simple_srand(3); - printk(PRINT_PREF "writing whole device\n"); + pr_info("writing whole device\n"); for (i = 0; i < ebcnt; ++i) { if (bbt[i]) continue; @@ -475,14 +475,14 @@ static int __init mtd_subpagetest_init(void) if (unlikely(err)) goto out; if (i % 256 == 0) - printk(PRINT_PREF "written up to eraseblock %u\n", i); + pr_info("written up to eraseblock %u\n", i); cond_resched(); } - printk(PRINT_PREF "written %u eraseblocks\n", i); + pr_info("written %u eraseblocks\n", i); /* Check all eraseblocks */ simple_srand(3); - printk(PRINT_PREF "verifying all eraseblocks\n"); + pr_info("verifying all eraseblocks\n"); for (i = 0; i < ebcnt; ++i) { if (bbt[i]) continue; @@ -490,10 +490,10 @@ static int __init mtd_subpagetest_init(void) if (unlikely(err)) goto out; if (i % 256 == 0) - printk(PRINT_PREF "verified up to eraseblock %u\n", i); + pr_info("verified up to eraseblock %u\n", i); cond_resched(); } - printk(PRINT_PREF "verified %u eraseblocks\n", i); + pr_info("verified %u eraseblocks\n", i); err = erase_whole_device(); if (err) @@ -503,7 +503,7 @@ static int __init mtd_subpagetest_init(void) if (err) goto out; - printk(PRINT_PREF "finished with %d errors\n", errcnt); + pr_info("finished with %d errors\n", errcnt); out: kfree(bbt); @@ -511,7 +511,7 @@ out: kfree(writebuf); put_mtd_device(mtd); if (err) - printk(PRINT_PREF "error %d occurred\n", err); + pr_info("error %d occurred\n", err); printk(KERN_INFO "=================================================\n"); return err; } diff --git a/drivers/mtd/tests/mtd_torturetest.c b/drivers/mtd/tests/mtd_torturetest.c index b65861bc7b8e..c4cde1e9eddb 100644 --- a/drivers/mtd/tests/mtd_torturetest.c +++ b/drivers/mtd/tests/mtd_torturetest.c @@ -23,6 +23,8 @@ * damage caused by this program. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/init.h> #include <linux/module.h> #include <linux/moduleparam.h> @@ -31,7 +33,6 @@ #include <linux/slab.h> #include <linux/sched.h> -#define PRINT_PREF KERN_INFO "mtd_torturetest: " #define RETRIES 3 static int eb = 8; @@ -107,12 +108,12 @@ static inline int erase_eraseblock(int ebnum) err = mtd_erase(mtd, &ei); if (err) { - printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum); + pr_err("error %d while erasing EB %d\n", err, ebnum); return err; } if (ei.state == MTD_ERASE_FAILED) { - printk(PRINT_PREF "some erase error occurred at EB %d\n", + pr_err("some erase error occurred at EB %d\n", ebnum); return -EIO; } @@ -139,40 +140,40 @@ static inline int check_eraseblock(int ebnum, unsigned char *buf) retry: err = mtd_read(mtd, addr, len, &read, check_buf); if (mtd_is_bitflip(err)) - printk(PRINT_PREF "single bit flip occurred at EB %d " + pr_err("single bit flip occurred at EB %d " "MTD reported that it was fixed.\n", ebnum); else if (err) { - printk(PRINT_PREF "error %d while reading EB %d, " + pr_err("error %d while reading EB %d, " "read %zd\n", err, ebnum, read); return err; } if (read != len) { - printk(PRINT_PREF "failed to read %zd bytes from EB %d, " + pr_err("failed to read %zd bytes from EB %d, " "read only %zd, but no error reported\n", len, ebnum, read); return -EIO; } if (memcmp(buf, check_buf, len)) { - printk(PRINT_PREF "read wrong data from EB %d\n", ebnum); + pr_err("read wrong data from EB %d\n", ebnum); report_corrupt(check_buf, buf); if (retries++ < RETRIES) { /* Try read again */ yield(); - printk(PRINT_PREF "re-try reading data from EB %d\n", + pr_info("re-try reading data from EB %d\n", ebnum); goto retry; } else { - printk(PRINT_PREF "retried %d times, still errors, " + pr_info("retried %d times, still errors, " "give-up\n", RETRIES); return -EINVAL; } } if (retries != 0) - printk(PRINT_PREF "only attempt number %d was OK (!!!)\n", + pr_info("only attempt number %d was OK (!!!)\n", retries); return 0; @@ -191,12 +192,12 @@ static inline int write_pattern(int ebnum, void *buf) } err = mtd_write(mtd, addr, len, &written, buf); if (err) { - printk(PRINT_PREF "error %d while writing EB %d, written %zd" + pr_err("error %d while writing EB %d, written %zd" " bytes\n", err, ebnum, written); return err; } if (written != len) { - printk(PRINT_PREF "written only %zd bytes of %zd, but no error" + pr_info("written only %zd bytes of %zd, but no error" " reported\n", written, len); return -EIO; } @@ -211,64 +212,64 @@ static int __init tort_init(void) printk(KERN_INFO "\n"); printk(KERN_INFO "=================================================\n"); - printk(PRINT_PREF "Warning: this program is trying to wear out your " + pr_info("Warning: this program is trying to wear out your " "flash, stop it if this is not wanted.\n"); if (dev < 0) { - printk(PRINT_PREF "Please specify a valid mtd-device via module paramter\n"); - printk(KERN_CRIT "CAREFUL: This test wipes all data on the specified MTD device!\n"); + pr_info("Please specify a valid mtd-device via module parameter\n"); + pr_crit("CAREFUL: This test wipes all data on the specified MTD device!\n"); return -EINVAL; } - printk(PRINT_PREF "MTD device: %d\n", dev); - printk(PRINT_PREF "torture %d eraseblocks (%d-%d) of mtd%d\n", + pr_info("MTD device: %d\n", dev); + pr_info("torture %d eraseblocks (%d-%d) of mtd%d\n", ebcnt, eb, eb + ebcnt - 1, dev); if (pgcnt) - printk(PRINT_PREF "torturing just %d pages per eraseblock\n", + pr_info("torturing just %d pages per eraseblock\n", pgcnt); - printk(PRINT_PREF "write verify %s\n", check ? "enabled" : "disabled"); + pr_info("write verify %s\n", check ? "enabled" : "disabled"); mtd = get_mtd_device(NULL, dev); if (IS_ERR(mtd)) { err = PTR_ERR(mtd); - printk(PRINT_PREF "error: cannot get MTD device\n"); + pr_err("error: cannot get MTD device\n"); return err; } if (mtd->writesize == 1) { - printk(PRINT_PREF "not NAND flash, assume page size is 512 " + pr_info("not NAND flash, assume page size is 512 " "bytes.\n"); pgsize = 512; } else pgsize = mtd->writesize; if (pgcnt && (pgcnt > mtd->erasesize / pgsize || pgcnt < 0)) { - printk(PRINT_PREF "error: invalid pgcnt value %d\n", pgcnt); + pr_err("error: invalid pgcnt value %d\n", pgcnt); goto out_mtd; } err = -ENOMEM; patt_5A5 = kmalloc(mtd->erasesize, GFP_KERNEL); if (!patt_5A5) { - printk(PRINT_PREF "error: cannot allocate memory\n"); + pr_err("error: cannot allocate memory\n"); goto out_mtd; } patt_A5A = kmalloc(mtd->erasesize, GFP_KERNEL); if (!patt_A5A) { - printk(PRINT_PREF "error: cannot allocate memory\n"); + pr_err("error: cannot allocate memory\n"); goto out_patt_5A5; } patt_FF = kmalloc(mtd->erasesize, GFP_KERNEL); if (!patt_FF) { - printk(PRINT_PREF "error: cannot allocate memory\n"); + pr_err("error: cannot allocate memory\n"); goto out_patt_A5A; } check_buf = kmalloc(mtd->erasesize, GFP_KERNEL); if (!check_buf) { - printk(PRINT_PREF "error: cannot allocate memory\n"); + pr_err("error: cannot allocate memory\n"); goto out_patt_FF; } @@ -295,13 +296,13 @@ static int __init tort_init(void) err = mtd_block_isbad(mtd, (loff_t)i * mtd->erasesize); if (err < 0) { - printk(PRINT_PREF "block_isbad() returned %d " + pr_info("block_isbad() returned %d " "for EB %d\n", err, i); goto out; } if (err) { - printk("EB %d is bad. Skip it.\n", i); + pr_err("EB %d is bad. Skip it.\n", i); bad_ebs[i - eb] = 1; } } @@ -329,7 +330,7 @@ static int __init tort_init(void) continue; err = check_eraseblock(i, patt_FF); if (err) { - printk(PRINT_PREF "verify failed" + pr_info("verify failed" " for 0xFF... pattern\n"); goto out; } @@ -362,7 +363,7 @@ static int __init tort_init(void) patt = patt_A5A; err = check_eraseblock(i, patt); if (err) { - printk(PRINT_PREF "verify failed for %s" + pr_info("verify failed for %s" " pattern\n", ((eb + erase_cycles) & 1) ? "0x55AA55..." : "0xAA55AA..."); @@ -380,7 +381,7 @@ static int __init tort_init(void) stop_timing(); ms = (finish.tv_sec - start.tv_sec) * 1000 + (finish.tv_usec - start.tv_usec) / 1000; - printk(PRINT_PREF "%08u erase cycles done, took %lu " + pr_info("%08u erase cycles done, took %lu " "milliseconds (%lu seconds)\n", erase_cycles, ms, ms / 1000); start_timing(); @@ -391,7 +392,7 @@ static int __init tort_init(void) } out: - printk(PRINT_PREF "finished after %u erase cycles\n", + pr_info("finished after %u erase cycles\n", erase_cycles); kfree(check_buf); out_patt_FF: @@ -403,7 +404,7 @@ out_patt_5A5: out_mtd: put_mtd_device(mtd); if (err) - printk(PRINT_PREF "error %d occurred during torturing\n", err); + pr_info("error %d occurred during torturing\n", err); printk(KERN_INFO "=================================================\n"); return err; } @@ -441,9 +442,9 @@ static void report_corrupt(unsigned char *read, unsigned char *written) &bits) >= 0) pages++; - printk(PRINT_PREF "verify fails on %d pages, %d bytes/%d bits\n", + pr_info("verify fails on %d pages, %d bytes/%d bits\n", pages, bytes, bits); - printk(PRINT_PREF "The following is a list of all differences between" + pr_info("The following is a list of all differences between" " what was read from flash and what was expected\n"); for (i = 0; i < check_len; i += pgsize) { @@ -457,7 +458,7 @@ static void report_corrupt(unsigned char *read, unsigned char *written) printk("-------------------------------------------------------" "----------------------------------\n"); - printk(PRINT_PREF "Page %zd has %d bytes/%d bits failing verify," + pr_info("Page %zd has %d bytes/%d bits failing verify," " starting at offset 0x%x\n", (mtd->erasesize - check_len + i) / pgsize, bytes, bits, first); diff --git a/drivers/mtd/ubi/attach.c b/drivers/mtd/ubi/attach.c index fec406b4553d..c071d410488f 100644 --- a/drivers/mtd/ubi/attach.c +++ b/drivers/mtd/ubi/attach.c @@ -322,7 +322,6 @@ static struct ubi_ainf_volume *add_volume(struct ubi_attach_info *ai, int ubi_compare_lebs(struct ubi_device *ubi, const struct ubi_ainf_peb *aeb, int pnum, const struct ubi_vid_hdr *vid_hdr) { - void *buf; int len, err, second_is_newer, bitflips = 0, corrupted = 0; uint32_t data_crc, crc; struct ubi_vid_hdr *vh = NULL; @@ -393,18 +392,14 @@ int ubi_compare_lebs(struct ubi_device *ubi, const struct ubi_ainf_peb *aeb, /* Read the data of the copy and check the CRC */ len = be32_to_cpu(vid_hdr->data_size); - buf = vmalloc(len); - if (!buf) { - err = -ENOMEM; - goto out_free_vidh; - } - err = ubi_io_read_data(ubi, buf, pnum, 0, len); + mutex_lock(&ubi->buf_mutex); + err = ubi_io_read_data(ubi, ubi->peb_buf, pnum, 0, len); if (err && err != UBI_IO_BITFLIPS && !mtd_is_eccerr(err)) - goto out_free_buf; + goto out_unlock; data_crc = be32_to_cpu(vid_hdr->data_crc); - crc = crc32(UBI_CRC32_INIT, buf, len); + crc = crc32(UBI_CRC32_INIT, ubi->peb_buf, len); if (crc != data_crc) { dbg_bld("PEB %d CRC error: calculated %#08x, must be %#08x", pnum, crc, data_crc); @@ -415,8 +410,8 @@ int ubi_compare_lebs(struct ubi_device *ubi, const struct ubi_ainf_peb *aeb, dbg_bld("PEB %d CRC is OK", pnum); bitflips = !!err; } + mutex_unlock(&ubi->buf_mutex); - vfree(buf); ubi_free_vid_hdr(ubi, vh); if (second_is_newer) @@ -426,8 +421,8 @@ int ubi_compare_lebs(struct ubi_device *ubi, const struct ubi_ainf_peb *aeb, return second_is_newer | (bitflips << 1) | (corrupted << 2); -out_free_buf: - vfree(buf); +out_unlock: + mutex_unlock(&ubi->buf_mutex); out_free_vidh: ubi_free_vid_hdr(ubi, vh); return err; @@ -1453,7 +1448,7 @@ int ubi_attach(struct ubi_device *ubi, int force_scan) goto out_wl; #ifdef CONFIG_MTD_UBI_FASTMAP - if (ubi->fm && ubi->dbg->chk_gen) { + if (ubi->fm && ubi_dbg_chk_gen(ubi)) { struct ubi_attach_info *scan_ai; scan_ai = alloc_ai("ubi_ckh_aeb_slab_cache"); @@ -1503,7 +1498,7 @@ static int self_check_ai(struct ubi_device *ubi, struct ubi_attach_info *ai) struct ubi_ainf_peb *aeb, *last_aeb; uint8_t *buf; - if (!ubi->dbg->chk_gen) + if (!ubi_dbg_chk_gen(ubi)) return 0; /* diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index 344b4cb49d4e..a56133585e92 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c @@ -825,8 +825,7 @@ static int autoresize(struct ubi_device *ubi, int vol_id) * No available PEBs to re-size the volume, clear the flag on * flash and exit. */ - memcpy(&vtbl_rec, &ubi->vtbl[vol_id], - sizeof(struct ubi_vtbl_record)); + vtbl_rec = ubi->vtbl[vol_id]; err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec); if (err) ubi_err("cannot clean auto-resize flag for volume %d", @@ -986,14 +985,10 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, if (!ubi->fm_buf) goto out_free; #endif - err = ubi_debugging_init_dev(ubi); - if (err) - goto out_free; - err = ubi_attach(ubi, 0); if (err) { ubi_err("failed to attach mtd%d, error %d", mtd->index, err); - goto out_debugging; + goto out_free; } if (ubi->autoresize_vol_id != -1) { @@ -1060,8 +1055,6 @@ out_detach: ubi_wl_close(ubi); ubi_free_internal_volumes(ubi); vfree(ubi->vtbl); -out_debugging: - ubi_debugging_exit_dev(ubi); out_free: vfree(ubi->peb_buf); vfree(ubi->fm_buf); @@ -1139,7 +1132,6 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway) ubi_free_internal_volumes(ubi); vfree(ubi->vtbl); put_mtd_device(ubi->mtd); - ubi_debugging_exit_dev(ubi); vfree(ubi->peb_buf); vfree(ubi->fm_buf); ubi_msg("mtd%d is detached from ubi%d", ubi->mtd->index, ubi->ubi_num); diff --git a/drivers/mtd/ubi/debug.c b/drivers/mtd/ubi/debug.c index 26908a59506b..63cb1d7236ce 100644 --- a/drivers/mtd/ubi/debug.c +++ b/drivers/mtd/ubi/debug.c @@ -217,32 +217,6 @@ void ubi_dump_mkvol_req(const struct ubi_mkvol_req *req) pr_err("\t1st 16 characters of name: %s\n", nm); } -/** - * ubi_debugging_init_dev - initialize debugging for an UBI device. - * @ubi: UBI device description object - * - * This function initializes debugging-related data for UBI device @ubi. - * Returns zero in case of success and a negative error code in case of - * failure. - */ -int ubi_debugging_init_dev(struct ubi_device *ubi) -{ - ubi->dbg = kzalloc(sizeof(struct ubi_debug_info), GFP_KERNEL); - if (!ubi->dbg) - return -ENOMEM; - - return 0; -} - -/** - * ubi_debugging_exit_dev - free debugging data for an UBI device. - * @ubi: UBI device description object - */ -void ubi_debugging_exit_dev(struct ubi_device *ubi) -{ - kfree(ubi->dbg); -} - /* * Root directory for UBI stuff in debugfs. Contains sub-directories which * contain the stuff specific to particular UBI devices. @@ -295,7 +269,7 @@ static ssize_t dfs_file_read(struct file *file, char __user *user_buf, ubi = ubi_get_device(ubi_num); if (!ubi) return -ENODEV; - d = ubi->dbg; + d = &ubi->dbg; if (dent == d->dfs_chk_gen) val = d->chk_gen; @@ -341,7 +315,7 @@ static ssize_t dfs_file_write(struct file *file, const char __user *user_buf, ubi = ubi_get_device(ubi_num); if (!ubi) return -ENODEV; - d = ubi->dbg; + d = &ubi->dbg; buf_size = min_t(size_t, count, (sizeof(buf) - 1)); if (copy_from_user(buf, user_buf, buf_size)) { @@ -398,7 +372,7 @@ int ubi_debugfs_init_dev(struct ubi_device *ubi) unsigned long ubi_num = ubi->ubi_num; const char *fname; struct dentry *dent; - struct ubi_debug_info *d = ubi->dbg; + struct ubi_debug_info *d = &ubi->dbg; if (!IS_ENABLED(CONFIG_DEBUG_FS)) return 0; @@ -471,5 +445,5 @@ out: void ubi_debugfs_exit_dev(struct ubi_device *ubi) { if (IS_ENABLED(CONFIG_DEBUG_FS)) - debugfs_remove_recursive(ubi->dbg->dfs_dir); + debugfs_remove_recursive(ubi->dbg.dfs_dir); } diff --git a/drivers/mtd/ubi/debug.h b/drivers/mtd/ubi/debug.h index 3dbc877d9663..33f8f3b2c9b2 100644 --- a/drivers/mtd/ubi/debug.h +++ b/drivers/mtd/ubi/debug.h @@ -60,51 +60,11 @@ void ubi_dump_aeb(const struct ubi_ainf_peb *aeb, int type); void ubi_dump_mkvol_req(const struct ubi_mkvol_req *req); int ubi_self_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len); -int ubi_debugging_init_dev(struct ubi_device *ubi); -void ubi_debugging_exit_dev(struct ubi_device *ubi); int ubi_debugfs_init(void); void ubi_debugfs_exit(void); int ubi_debugfs_init_dev(struct ubi_device *ubi); void ubi_debugfs_exit_dev(struct ubi_device *ubi); -/* - * The UBI debugfs directory name pattern and maximum name length (3 for "ubi" - * + 2 for the number plus 1 for the trailing zero byte. - */ -#define UBI_DFS_DIR_NAME "ubi%d" -#define UBI_DFS_DIR_LEN (3 + 2 + 1) - -/** - * struct ubi_debug_info - debugging information for an UBI device. - * - * @chk_gen: if UBI general extra checks are enabled - * @chk_io: if UBI I/O extra checks are enabled - * @disable_bgt: disable the background task for testing purposes - * @emulate_bitflips: emulate bit-flips for testing purposes - * @emulate_io_failures: emulate write/erase failures for testing purposes - * @dfs_dir_name: name of debugfs directory containing files of this UBI device - * @dfs_dir: direntry object of the UBI device debugfs directory - * @dfs_chk_gen: debugfs knob to enable UBI general extra checks - * @dfs_chk_io: debugfs knob to enable UBI I/O extra checks - * @dfs_disable_bgt: debugfs knob to disable the background task - * @dfs_emulate_bitflips: debugfs knob to emulate bit-flips - * @dfs_emulate_io_failures: debugfs knob to emulate write/erase failures - */ -struct ubi_debug_info { - unsigned int chk_gen:1; - unsigned int chk_io:1; - unsigned int disable_bgt:1; - unsigned int emulate_bitflips:1; - unsigned int emulate_io_failures:1; - char dfs_dir_name[UBI_DFS_DIR_LEN + 1]; - struct dentry *dfs_dir; - struct dentry *dfs_chk_gen; - struct dentry *dfs_chk_io; - struct dentry *dfs_disable_bgt; - struct dentry *dfs_emulate_bitflips; - struct dentry *dfs_emulate_io_failures; -}; - /** * ubi_dbg_is_bgt_disabled - if the background thread is disabled. * @ubi: UBI device description object @@ -114,7 +74,7 @@ struct ubi_debug_info { */ static inline int ubi_dbg_is_bgt_disabled(const struct ubi_device *ubi) { - return ubi->dbg->disable_bgt; + return ubi->dbg.disable_bgt; } /** @@ -125,7 +85,7 @@ static inline int ubi_dbg_is_bgt_disabled(const struct ubi_device *ubi) */ static inline int ubi_dbg_is_bitflip(const struct ubi_device *ubi) { - if (ubi->dbg->emulate_bitflips) + if (ubi->dbg.emulate_bitflips) return !(random32() % 200); return 0; } @@ -139,7 +99,7 @@ static inline int ubi_dbg_is_bitflip(const struct ubi_device *ubi) */ static inline int ubi_dbg_is_write_failure(const struct ubi_device *ubi) { - if (ubi->dbg->emulate_io_failures) + if (ubi->dbg.emulate_io_failures) return !(random32() % 500); return 0; } @@ -153,9 +113,18 @@ static inline int ubi_dbg_is_write_failure(const struct ubi_device *ubi) */ static inline int ubi_dbg_is_erase_failure(const struct ubi_device *ubi) { - if (ubi->dbg->emulate_io_failures) + if (ubi->dbg.emulate_io_failures) return !(random32() % 400); return 0; } +static inline int ubi_dbg_chk_io(const struct ubi_device *ubi) +{ + return ubi->dbg.chk_io; +} + +static inline int ubi_dbg_chk_gen(const struct ubi_device *ubi) +{ + return ubi->dbg.chk_gen; +} #endif /* !__UBI_DEBUG_H__ */ diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c index 1a5f53c090d4..0648c6996d43 100644 --- a/drivers/mtd/ubi/fastmap.c +++ b/drivers/mtd/ubi/fastmap.c @@ -814,10 +814,8 @@ static int ubi_attach_fastmap(struct ubi_device *ubi, if (max_sqnum > ai->max_sqnum) ai->max_sqnum = max_sqnum; - list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &free, u.list) { - list_del(&tmp_aeb->u.list); - list_add_tail(&tmp_aeb->u.list, &ai->free); - } + list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &free, u.list) + list_move_tail(&tmp_aeb->u.list, &ai->free); /* * If fastmap is leaking PEBs (must not happen), raise a diff --git a/drivers/mtd/ubi/gluebi.c b/drivers/mtd/ubi/gluebi.c index 4bd4db8c84c9..b93807b4c459 100644 --- a/drivers/mtd/ubi/gluebi.c +++ b/drivers/mtd/ubi/gluebi.c @@ -171,17 +171,17 @@ static void gluebi_put_device(struct mtd_info *mtd) static int gluebi_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, unsigned char *buf) { - int err = 0, lnum, offs, total_read; + int err = 0, lnum, offs, bytes_left; struct gluebi_device *gluebi; gluebi = container_of(mtd, struct gluebi_device, mtd); lnum = div_u64_rem(from, mtd->erasesize, &offs); - total_read = len; - while (total_read) { + bytes_left = len; + while (bytes_left) { size_t to_read = mtd->erasesize - offs; - if (to_read > total_read) - to_read = total_read; + if (to_read > bytes_left) + to_read = bytes_left; err = ubi_read(gluebi->desc, lnum, buf, offs, to_read); if (err) @@ -189,11 +189,11 @@ static int gluebi_read(struct mtd_info *mtd, loff_t from, size_t len, lnum += 1; offs = 0; - total_read -= to_read; + bytes_left -= to_read; buf += to_read; } - *retlen = len - total_read; + *retlen = len - bytes_left; return err; } @@ -211,7 +211,7 @@ static int gluebi_read(struct mtd_info *mtd, loff_t from, size_t len, static int gluebi_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) { - int err = 0, lnum, offs, total_written; + int err = 0, lnum, offs, bytes_left; struct gluebi_device *gluebi; gluebi = container_of(mtd, struct gluebi_device, mtd); @@ -220,12 +220,12 @@ static int gluebi_write(struct mtd_info *mtd, loff_t to, size_t len, if (len % mtd->writesize || offs % mtd->writesize) return -EINVAL; - total_written = len; - while (total_written) { + bytes_left = len; + while (bytes_left) { size_t to_write = mtd->erasesize - offs; - if (to_write > total_written) - to_write = total_written; + if (to_write > bytes_left) + to_write = bytes_left; err = ubi_leb_write(gluebi->desc, lnum, buf, offs, to_write); if (err) @@ -233,11 +233,11 @@ static int gluebi_write(struct mtd_info *mtd, loff_t to, size_t len, lnum += 1; offs = 0; - total_written -= to_write; + bytes_left -= to_write; buf += to_write; } - *retlen = len - total_written; + *retlen = len - bytes_left; return err; } diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index 78a1dcbf2107..bf79def40126 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c @@ -1132,7 +1132,7 @@ static int self_check_not_bad(const struct ubi_device *ubi, int pnum) { int err; - if (!ubi->dbg->chk_io) + if (!ubi_dbg_chk_io(ubi)) return 0; err = ubi_io_is_bad(ubi, pnum); @@ -1159,7 +1159,7 @@ static int self_check_ec_hdr(const struct ubi_device *ubi, int pnum, int err; uint32_t magic; - if (!ubi->dbg->chk_io) + if (!ubi_dbg_chk_io(ubi)) return 0; magic = be32_to_cpu(ec_hdr->magic); @@ -1197,7 +1197,7 @@ static int self_check_peb_ec_hdr(const struct ubi_device *ubi, int pnum) uint32_t crc, hdr_crc; struct ubi_ec_hdr *ec_hdr; - if (!ubi->dbg->chk_io) + if (!ubi_dbg_chk_io(ubi)) return 0; ec_hdr = kzalloc(ubi->ec_hdr_alsize, GFP_NOFS); @@ -1241,7 +1241,7 @@ static int self_check_vid_hdr(const struct ubi_device *ubi, int pnum, int err; uint32_t magic; - if (!ubi->dbg->chk_io) + if (!ubi_dbg_chk_io(ubi)) return 0; magic = be32_to_cpu(vid_hdr->magic); @@ -1282,7 +1282,7 @@ static int self_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum) struct ubi_vid_hdr *vid_hdr; void *p; - if (!ubi->dbg->chk_io) + if (!ubi_dbg_chk_io(ubi)) return 0; vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS); @@ -1334,7 +1334,7 @@ static int self_check_write(struct ubi_device *ubi, const void *buf, int pnum, void *buf1; loff_t addr = (loff_t)pnum * ubi->peb_size + offset; - if (!ubi->dbg->chk_io) + if (!ubi_dbg_chk_io(ubi)) return 0; buf1 = __vmalloc(len, GFP_NOFS, PAGE_KERNEL); @@ -1398,7 +1398,7 @@ int ubi_self_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len) void *buf; loff_t addr = (loff_t)pnum * ubi->peb_size + offset; - if (!ubi->dbg->chk_io) + if (!ubi_dbg_chk_io(ubi)) return 0; buf = __vmalloc(len, GFP_NOFS, PAGE_KERNEL); diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index 7d57469723cf..8ea6297a208f 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h @@ -85,6 +85,13 @@ #define UBI_UNKNOWN -1 /* + * The UBI debugfs directory name pattern and maximum name length (3 for "ubi" + * + 2 for the number plus 1 for the trailing zero byte. + */ +#define UBI_DFS_DIR_NAME "ubi%d" +#define UBI_DFS_DIR_LEN (3 + 2 + 1) + +/* * Error codes returned by the I/O sub-system. * * UBI_IO_FF: the read region of flash contains only 0xFFs @@ -342,6 +349,37 @@ struct ubi_volume_desc { struct ubi_wl_entry; /** + * struct ubi_debug_info - debugging information for an UBI device. + * + * @chk_gen: if UBI general extra checks are enabled + * @chk_io: if UBI I/O extra checks are enabled + * @disable_bgt: disable the background task for testing purposes + * @emulate_bitflips: emulate bit-flips for testing purposes + * @emulate_io_failures: emulate write/erase failures for testing purposes + * @dfs_dir_name: name of debugfs directory containing files of this UBI device + * @dfs_dir: direntry object of the UBI device debugfs directory + * @dfs_chk_gen: debugfs knob to enable UBI general extra checks + * @dfs_chk_io: debugfs knob to enable UBI I/O extra checks + * @dfs_disable_bgt: debugfs knob to disable the background task + * @dfs_emulate_bitflips: debugfs knob to emulate bit-flips + * @dfs_emulate_io_failures: debugfs knob to emulate write/erase failures + */ +struct ubi_debug_info { + unsigned int chk_gen:1; + unsigned int chk_io:1; + unsigned int disable_bgt:1; + unsigned int emulate_bitflips:1; + unsigned int emulate_io_failures:1; + char dfs_dir_name[UBI_DFS_DIR_LEN + 1]; + struct dentry *dfs_dir; + struct dentry *dfs_chk_gen; + struct dentry *dfs_chk_io; + struct dentry *dfs_disable_bgt; + struct dentry *dfs_emulate_bitflips; + struct dentry *dfs_emulate_io_failures; +}; + +/** * struct ubi_device - UBI device description structure * @dev: UBI device object to use the the Linux device model * @cdev: character device object to create character device @@ -545,7 +583,7 @@ struct ubi_device { struct mutex buf_mutex; struct mutex ckvol_mutex; - struct ubi_debug_info *dbg; + struct ubi_debug_info dbg; }; /** diff --git a/drivers/mtd/ubi/upd.c b/drivers/mtd/ubi/upd.c index 9f2ebd8750e7..ec2c2dc1c1ca 100644 --- a/drivers/mtd/ubi/upd.c +++ b/drivers/mtd/ubi/upd.c @@ -64,8 +64,7 @@ static int set_update_marker(struct ubi_device *ubi, struct ubi_volume *vol) return 0; } - memcpy(&vtbl_rec, &ubi->vtbl[vol->vol_id], - sizeof(struct ubi_vtbl_record)); + vtbl_rec = ubi->vtbl[vol->vol_id]; vtbl_rec.upd_marker = 1; mutex_lock(&ubi->device_mutex); @@ -93,8 +92,7 @@ static int clear_update_marker(struct ubi_device *ubi, struct ubi_volume *vol, dbg_gen("clear update marker for volume %d", vol->vol_id); - memcpy(&vtbl_rec, &ubi->vtbl[vol->vol_id], - sizeof(struct ubi_vtbl_record)); + vtbl_rec = ubi->vtbl[vol->vol_id]; ubi_assert(vol->upd_marker && vtbl_rec.upd_marker); vtbl_rec.upd_marker = 0; diff --git a/drivers/mtd/ubi/vmt.c b/drivers/mtd/ubi/vmt.c index 9169e58c262e..8330703c098f 100644 --- a/drivers/mtd/ubi/vmt.c +++ b/drivers/mtd/ubi/vmt.c @@ -535,7 +535,7 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs) } /* Change volume table record */ - memcpy(&vtbl_rec, &ubi->vtbl[vol_id], sizeof(struct ubi_vtbl_record)); + vtbl_rec = ubi->vtbl[vol_id]; vtbl_rec.reserved_pebs = cpu_to_be32(reserved_pebs); err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec); if (err) @@ -847,7 +847,7 @@ static int self_check_volumes(struct ubi_device *ubi) { int i, err = 0; - if (!ubi->dbg->chk_gen) + if (!ubi_dbg_chk_gen(ubi)) return 0; for (i = 0; i < ubi->vtbl_slots; i++) { diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c index 926e3df14fb2..d77b1c1d7c72 100644 --- a/drivers/mtd/ubi/vtbl.c +++ b/drivers/mtd/ubi/vtbl.c @@ -858,7 +858,7 @@ out_free: */ static void self_vtbl_check(const struct ubi_device *ubi) { - if (!ubi->dbg->chk_gen) + if (!ubi_dbg_chk_gen(ubi)) return; if (vtbl_check(ubi, ubi->vtbl)) { diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index da7b44998b40..5df49d3cb5c7 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c @@ -1,5 +1,4 @@ /* - * @ubi: UBI device description object * Copyright (c) International Business Machines Corp., 2006 * * This program is free software; you can redistribute it and/or modify @@ -498,7 +497,7 @@ out: * @ubi: UBI device description object * * This function returns a physical eraseblock in case of success and a - * negative error code in case of failure. Might sleep. + * negative error code in case of failure. */ static int __wl_get_peb(struct ubi_device *ubi) { @@ -540,13 +539,6 @@ retry: * ubi_wl_get_peb() after removing e from the pool. */ prot_queue_add(ubi, e); #endif - err = ubi_self_check_all_ff(ubi, e->pnum, ubi->vid_hdr_aloffset, - ubi->peb_size - ubi->vid_hdr_aloffset); - if (err) { - ubi_err("new PEB %d does not contain all 0xFF bytes", e->pnum); - return err; - } - return e->pnum; } @@ -679,17 +671,30 @@ static struct ubi_wl_entry *get_peb_for_wl(struct ubi_device *ubi) #else static struct ubi_wl_entry *get_peb_for_wl(struct ubi_device *ubi) { - return find_wl_entry(ubi, &ubi->free, WL_FREE_MAX_DIFF); + struct ubi_wl_entry *e; + + e = find_wl_entry(ubi, &ubi->free, WL_FREE_MAX_DIFF); + self_check_in_wl_tree(ubi, e, &ubi->free); + rb_erase(&e->u.rb, &ubi->free); + + return e; } int ubi_wl_get_peb(struct ubi_device *ubi) { - int peb; + int peb, err; spin_lock(&ubi->wl_lock); peb = __wl_get_peb(ubi); spin_unlock(&ubi->wl_lock); + err = ubi_self_check_all_ff(ubi, peb, ubi->vid_hdr_aloffset, + ubi->peb_size - ubi->vid_hdr_aloffset); + if (err) { + ubi_err("new PEB %d does not contain all 0xFF bytes", peb); + return err; + } + return peb; } #endif @@ -2044,7 +2049,7 @@ static int self_check_ec(struct ubi_device *ubi, int pnum, int ec) long long read_ec; struct ubi_ec_hdr *ec_hdr; - if (!ubi->dbg->chk_gen) + if (!ubi_dbg_chk_gen(ubi)) return 0; ec_hdr = kzalloc(ubi->ec_hdr_alsize, GFP_NOFS); @@ -2084,7 +2089,7 @@ out_free: static int self_check_in_wl_tree(const struct ubi_device *ubi, struct ubi_wl_entry *e, struct rb_root *root) { - if (!ubi->dbg->chk_gen) + if (!ubi_dbg_chk_gen(ubi)) return 0; if (in_wl_tree(e, root)) @@ -2110,7 +2115,7 @@ static int self_check_in_pq(const struct ubi_device *ubi, struct ubi_wl_entry *p; int i; - if (!ubi->dbg->chk_gen) + if (!ubi_dbg_chk_gen(ubi)) return 0; for (i = 0; i < UBI_PROT_QUEUE_LEN; ++i) |