Merge git://git.infradead.org/mtd-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 17 Jan 2011 19:15:30 +0000 (11:15 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 17 Jan 2011 19:15:30 +0000 (11:15 -0800)
* git://git.infradead.org/mtd-2.6: (59 commits)
  mtd: mtdpart: disallow reading OOB past the end of the partition
  mtd: pxa3xx_nand: NULL dereference in pxa3xx_nand_probe
  UBI: use mtd->writebufsize to set minimal I/O unit size
  mtd: initialize writebufsize in the MTD object of a partition
  mtd: onenand: add mtd->writebufsize initialization
  mtd: nand: add mtd->writebufsize initialization
  mtd: cfi: add writebufsize initialization
  mtd: add writebufsize field to mtd_info struct
  mtd: OneNAND: OMAP2/3: prevent regulator sleeping while OneNAND is in use
  mtd: OneNAND: add enable / disable methods to onenand_chip
  mtd: m25p80: Fix JEDEC ID for AT26DF321
  mtd: txx9ndfmc: limit transfer bytes to 512 (ECC provides 6 bytes max)
  mtd: cfi_cmdset_0002: add support for Samsung K8D3x16UxC NOR chips
  mtd: cfi_cmdset_0002: add support for Samsung K8D6x16UxM NOR chips
  mtd: nand: ams-delta: drop omap_read/write, use ioremap
  mtd: m25p80: add debugging trace in sst_write
  mtd: nand: ams-delta: select for built-in by default
  mtd: OneNAND: lighten scary initial bad block messages
  mtd: OneNAND: OMAP2/3: add support for command line partitioning
  mtd: nand: rearrange ONFI revision checking, add ONFI 2.3
  ...

Fix up trivial conflict in drivers/mtd/Kconfig as per DavidW.

1  2 
arch/arm/mach-omap1/board-ams-delta.c
drivers/mtd/mtdchar.c
drivers/mtd/mtdoops.c
drivers/mtd/nand/nand_base.c
drivers/mtd/onenand/omap2.c

@@@ -28,7 -28,6 +28,7 @@@
  #include <asm/mach/arch.h>
  #include <asm/mach/map.h>
  
 +#include <plat/io.h>
  #include <plat/board-ams-delta.h>
  #include <mach/gpio.h>
  #include <plat/keypad.h>
  static u8 ams_delta_latch1_reg;
  static u16 ams_delta_latch2_reg;
  
 -static int ams_delta_keymap[] = {
 +static const unsigned int ams_delta_keymap[] = {
        KEY(0, 0, KEY_F1),              /* Advert    */
  
 -      KEY(3, 0, KEY_COFFEE),          /* Games     */
 -      KEY(2, 0, KEY_QUESTION),        /* Directory */
 -      KEY(3, 2, KEY_CONNECT),         /* Internet  */
 -      KEY(2, 1, KEY_SHOP),            /* Services  */
 +      KEY(0, 3, KEY_COFFEE),          /* Games     */
 +      KEY(0, 2, KEY_QUESTION),        /* Directory */
 +      KEY(2, 3, KEY_CONNECT),         /* Internet  */
 +      KEY(1, 2, KEY_SHOP),            /* Services  */
        KEY(1, 1, KEY_PHONE),           /* VoiceMail */
  
 -      KEY(1, 0, KEY_DELETE),          /* Delete    */
 +      KEY(0, 1, KEY_DELETE),          /* Delete    */
        KEY(2, 2, KEY_PLAY),            /* Play      */
 -      KEY(0, 1, KEY_PAGEUP),          /* Up        */
 -      KEY(3, 1, KEY_PAGEDOWN),        /* Down      */
 -      KEY(0, 2, KEY_EMAIL),           /* ReadEmail */
 -      KEY(1, 2, KEY_STOP),            /* Stop      */
 +      KEY(1, 0, KEY_PAGEUP),          /* Up        */
 +      KEY(1, 3, KEY_PAGEDOWN),        /* Down      */
 +      KEY(2, 0, KEY_EMAIL),           /* ReadEmail */
 +      KEY(2, 1, KEY_STOP),            /* Stop      */
  
        /* Numeric keypad portion */
 -      KEY(7, 0, KEY_KP1),
 -      KEY(6, 0, KEY_KP2),
 -      KEY(5, 0, KEY_KP3),
 -      KEY(7, 1, KEY_KP4),
 -      KEY(6, 1, KEY_KP5),
 -      KEY(5, 1, KEY_KP6),
 -      KEY(7, 2, KEY_KP7),
 -      KEY(6, 2, KEY_KP8),
 -      KEY(5, 2, KEY_KP9),
 -      KEY(6, 3, KEY_KP0),
 -      KEY(7, 3, KEY_KPASTERISK),
 -      KEY(5, 3, KEY_KPDOT),           /* # key     */
 -      KEY(2, 7, KEY_NUMLOCK),         /* Mute      */
 -      KEY(1, 7, KEY_KPMINUS),         /* Recall    */
 -      KEY(1, 6, KEY_KPPLUS),          /* Redial    */
 -      KEY(6, 7, KEY_KPSLASH),         /* Handsfree */
 -      KEY(0, 6, KEY_ENTER),           /* Video     */
 -
 -      KEY(4, 7, KEY_CAMERA),          /* Photo     */
 -
 -      KEY(4, 0, KEY_F2),              /* Home      */
 -      KEY(4, 1, KEY_F3),              /* Office    */
 -      KEY(4, 2, KEY_F4),              /* Mobile    */
 +      KEY(0, 7, KEY_KP1),
 +      KEY(0, 6, KEY_KP2),
 +      KEY(0, 5, KEY_KP3),
 +      KEY(1, 7, KEY_KP4),
 +      KEY(1, 6, KEY_KP5),
 +      KEY(1, 5, KEY_KP6),
 +      KEY(2, 7, KEY_KP7),
 +      KEY(2, 6, KEY_KP8),
 +      KEY(2, 5, KEY_KP9),
 +      KEY(3, 6, KEY_KP0),
 +      KEY(3, 7, KEY_KPASTERISK),
 +      KEY(3, 5, KEY_KPDOT),           /* # key     */
 +      KEY(7, 2, KEY_NUMLOCK),         /* Mute      */
 +      KEY(7, 1, KEY_KPMINUS),         /* Recall    */
 +      KEY(6, 1, KEY_KPPLUS),          /* Redial    */
 +      KEY(7, 6, KEY_KPSLASH),         /* Handsfree */
 +      KEY(6, 0, KEY_ENTER),           /* Video     */
 +
 +      KEY(7, 4, KEY_CAMERA),          /* Photo     */
 +
 +      KEY(0, 4, KEY_F2),              /* Home      */
 +      KEY(1, 4, KEY_F3),              /* Office    */
 +      KEY(2, 4, KEY_F4),              /* Mobile    */
        KEY(7, 7, KEY_F5),              /* SMS       */
 -      KEY(5, 7, KEY_F6),              /* Email     */
 +      KEY(7, 5, KEY_F6),              /* Email     */
  
        /* QWERTY portion of keypad */
 -      KEY(4, 3, KEY_Q),
 +      KEY(3, 4, KEY_Q),
        KEY(3, 3, KEY_W),
 -      KEY(2, 3, KEY_E),
 -      KEY(1, 3, KEY_R),
 -      KEY(0, 3, KEY_T),
 -      KEY(7, 4, KEY_Y),
 -      KEY(6, 4, KEY_U),
 -      KEY(5, 4, KEY_I),
 +      KEY(3, 2, KEY_E),
 +      KEY(3, 1, KEY_R),
 +      KEY(3, 0, KEY_T),
 +      KEY(4, 7, KEY_Y),
 +      KEY(4, 6, KEY_U),
 +      KEY(4, 5, KEY_I),
        KEY(4, 4, KEY_O),
 -      KEY(3, 4, KEY_P),
 +      KEY(4, 3, KEY_P),
  
 -      KEY(2, 4, KEY_A),
 -      KEY(1, 4, KEY_S),
 -      KEY(0, 4, KEY_D),
 -      KEY(7, 5, KEY_F),
 -      KEY(6, 5, KEY_G),
 +      KEY(4, 2, KEY_A),
 +      KEY(4, 1, KEY_S),
 +      KEY(4, 0, KEY_D),
 +      KEY(5, 7, KEY_F),
 +      KEY(5, 6, KEY_G),
        KEY(5, 5, KEY_H),
 -      KEY(4, 5, KEY_J),
 -      KEY(3, 5, KEY_K),
 -      KEY(2, 5, KEY_L),
 +      KEY(5, 4, KEY_J),
 +      KEY(5, 3, KEY_K),
 +      KEY(5, 2, KEY_L),
  
 -      KEY(1, 5, KEY_Z),
 -      KEY(0, 5, KEY_X),
 -      KEY(7, 6, KEY_C),
 +      KEY(5, 1, KEY_Z),
 +      KEY(5, 0, KEY_X),
 +      KEY(6, 7, KEY_C),
        KEY(6, 6, KEY_V),
 -      KEY(5, 6, KEY_B),
 -      KEY(4, 6, KEY_N),
 -      KEY(3, 6, KEY_M),
 -      KEY(2, 6, KEY_SPACE),
 +      KEY(6, 5, KEY_B),
 +      KEY(6, 4, KEY_N),
 +      KEY(6, 3, KEY_M),
 +      KEY(6, 2, KEY_SPACE),
  
 -      KEY(0, 7, KEY_LEFTSHIFT),       /* Vol up    */
 -      KEY(3, 7, KEY_LEFTCTRL),        /* Vol down  */
 -
 -      0
 +      KEY(7, 0, KEY_LEFTSHIFT),       /* Vol up    */
 +      KEY(7, 3, KEY_LEFTCTRL),        /* Vol down  */
  };
  
  void ams_delta_latch1_write(u8 mask, u8 value)
@@@ -139,6 -140,7 +139,6 @@@ static void __init ams_delta_init_irq(v
  {
        omap1_init_common_hw();
        omap_init_irq();
 -      omap_gpio_init();
  }
  
  static struct map_desc ams_delta_io_desc[] __initdata = {
@@@ -179,6 -181,22 +179,22 @@@ static struct omap_board_config_kernel 
        { OMAP_TAG_LCD,         &ams_delta_lcd_config },
  };
  
+ static struct resource ams_delta_nand_resources[] = {
+       [0] = {
+               .start  = OMAP1_MPUIO_BASE,
+               .end    = OMAP1_MPUIO_BASE +
+                               OMAP_MPUIO_IO_CNTL + sizeof(u32) - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+ };
+ static struct platform_device ams_delta_nand_device = {
+       .name   = "ams-delta-nand",
+       .id     = -1,
+       .num_resources  = ARRAY_SIZE(ams_delta_nand_resources),
+       .resource       = ams_delta_nand_resources,
+ };
  static struct resource ams_delta_kp_resources[] = {
        [0] = {
                .start  = INT_KEYBOARD,
        },
  };
  
 +static const struct matrix_keymap_data ams_delta_keymap_data = {
 +      .keymap         = ams_delta_keymap,
 +      .keymap_size    = ARRAY_SIZE(ams_delta_keymap),
 +};
 +
  static struct omap_kp_platform_data ams_delta_kp_data = {
        .rows           = 8,
        .cols           = 8,
 -      .keymap         = ams_delta_keymap,
 -      .keymapsize     = ARRAY_SIZE(ams_delta_keymap),
 +      .keymap_data    = &ams_delta_keymap_data,
        .delay          = 9,
  };
  
@@@ -265,6 -279,7 +281,7 @@@ static struct omap1_cam_platform_data a
  };
  
  static struct platform_device *ams_delta_devices[] __initdata = {
+       &ams_delta_nand_device,
        &ams_delta_kp_device,
        &ams_delta_lcd_device,
        &ams_delta_led_device,
@@@ -309,14 -324,16 +326,14 @@@ static void __init ams_delta_init(void
  #endif
        platform_add_devices(ams_delta_devices, ARRAY_SIZE(ams_delta_devices));
  
 -#ifdef CONFIG_AMS_DELTA_FIQ
        ams_delta_init_fiq();
 -#endif
  
        omap_writew(omap_readw(ARM_RSTCT1) | 0x0004, ARM_RSTCT1);
  }
  
  static struct plat_serial8250_port ams_delta_modem_ports[] = {
        {
 -              .membase        = (void *) AMS_DELTA_MODEM_VIRT,
 +              .membase        = IOMEM(AMS_DELTA_MODEM_VIRT),
                .mapbase        = AMS_DELTA_MODEM_PHYS,
                .irq            = -EINVAL, /* changed later */
                .flags          = UPF_BOOT_AUTOCONF,
@@@ -340,9 -357,6 +357,9 @@@ static int __init ams_delta_modem_init(
  {
        int err;
  
 +      if (!machine_is_ams_delta())
 +              return -ENODEV;
 +
        omap_cfg_reg(M14_1510_GPIO2);
        ams_delta_modem_ports[0].irq =
                        gpio_to_irq(AMS_DELTA_GPIO_PIN_MODEM_IRQ);
diff --combined drivers/mtd/mtdchar.c
@@@ -522,10 -522,6 +522,6 @@@ static int mtd_blkpg_ioctl(struct mtd_i
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
  
-       /* Only master mtd device must be used to control partitions */
-       if (!mtd_is_master(mtd))
-               return -EINVAL;
        if (copy_from_user(&a, arg, sizeof(struct blkpg_ioctl_arg)))
                return -EFAULT;
  
        switch (a.op) {
        case BLKPG_ADD_PARTITION:
  
+               /* Only master mtd device must be used to add partitions */
+               if (mtd_is_partition(mtd))
+                       return -EINVAL;
                return mtd_add_partition(mtd, p.devname, p.start, p.length);
  
        case BLKPG_DEL_PARTITION:
@@@ -601,6 -601,7 +601,7 @@@ static int mtd_ioctl(struct file *file
        }
  
        case MEMGETINFO:
+               memset(&info, 0, sizeof(info));
                info.type       = mtd->type;
                info.flags      = mtd->flags;
                info.size       = mtd->size;
                info.oobsize    = mtd->oobsize;
                /* The below fields are obsolete */
                info.ecctype    = -1;
-               info.eccsize    = 0;
                if (copy_to_user(argp, &info, sizeof(struct mtd_info_user)))
                        return -EFAULT;
                break;
@@@ -1134,7 -1134,7 +1134,7 @@@ static const struct file_operations mtd
  static struct dentry *mtd_inodefs_mount(struct file_system_type *fs_type,
                                int flags, const char *dev_name, void *data)
  {
 -      return mount_pseudo(fs_type, "mtd_inode:", NULL, MTD_INODE_FS_MAGIC);
 +      return mount_pseudo(fs_type, "mtd_inode:", NULL, NULL, MTD_INODE_FS_MAGIC);
  }
  
  static struct file_system_type mtd_inodefs_type = {
diff --combined drivers/mtd/mtdoops.c
@@@ -307,11 -307,6 +307,11 @@@ static void mtdoops_do_dump(struct kmsg
        unsigned long l1_cpy, l2_cpy;
        char *dst;
  
 +      if (reason != KMSG_DUMP_OOPS &&
 +          reason != KMSG_DUMP_PANIC &&
 +          reason != KMSG_DUMP_KEXEC)
 +              return;
 +
        /* Only dump oopses if dump_oops is set */
        if (reason == KMSG_DUMP_OOPS && !dump_oops)
                return;
@@@ -401,7 -396,8 +401,8 @@@ static void mtdoops_notify_remove(struc
                printk(KERN_WARNING "mtdoops: could not unregister kmsg_dumper\n");
  
        cxt->mtd = NULL;
-       flush_scheduled_work();
+       flush_work_sync(&cxt->work_erase);
+       flush_work_sync(&cxt->work_write);
  }
  
  
@@@ -821,7 -821,7 +821,7 @@@ retry
   *
   * Wait for command done. This is a helper function for nand_wait used when
   * we are in interrupt context. May happen when in panic and trying to write
 - * an oops trough mtdoops.
 + * an oops through mtdoops.
   */
  static void panic_nand_wait(struct mtd_info *mtd, struct nand_chip *chip,
                            unsigned long timeo)
@@@ -2865,20 -2865,24 +2865,24 @@@ static int nand_flash_detect_onfi(struc
  
        /* check version */
        val = le16_to_cpu(p->revision);
-       if (val == 1 || val > (1 << 4)) {
-               printk(KERN_INFO "%s: unsupported ONFI version: %d\n",
-                                                               __func__, val);
-               return 0;
-       }
-       if (val & (1 << 4))
+       if (val & (1 << 5))
+               chip->onfi_version = 23;
+       else if (val & (1 << 4))
                chip->onfi_version = 22;
        else if (val & (1 << 3))
                chip->onfi_version = 21;
        else if (val & (1 << 2))
                chip->onfi_version = 20;
-       else
+       else if (val & (1 << 1))
                chip->onfi_version = 10;
+       else
+               chip->onfi_version = 0;
+       if (!chip->onfi_version) {
+               printk(KERN_INFO "%s: unsupported ONFI version: %d\n",
+                                                               __func__, val);
+               return 0;
+       }
  
        sanitize_string(p->manufacturer, sizeof(p->manufacturer));
        sanitize_string(p->model, sizeof(p->model));
        mtd->writesize = le32_to_cpu(p->byte_per_page);
        mtd->erasesize = le32_to_cpu(p->pages_per_block) * mtd->writesize;
        mtd->oobsize = le16_to_cpu(p->spare_bytes_per_page);
-       chip->chipsize = le32_to_cpu(p->blocks_per_lun) * mtd->erasesize;
+       chip->chipsize = (uint64_t)le32_to_cpu(p->blocks_per_lun) * mtd->erasesize;
        busw = 0;
        if (le16_to_cpu(p->features) & 1)
                busw = NAND_BUSWIDTH_16;
@@@ -3157,7 -3161,7 +3161,7 @@@ ident_done
        printk(KERN_INFO "NAND device: Manufacturer ID:"
                " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, *dev_id,
                nand_manuf_ids[maf_idx].name,
-       chip->onfi_version ? type->name : chip->onfi_params.model);
+               chip->onfi_version ? chip->onfi_params.model : type->name);
  
        return type;
  }
@@@ -3435,6 -3439,7 +3439,7 @@@ int nand_scan_tail(struct mtd_info *mtd
        mtd->resume = nand_resume;
        mtd->block_isbad = nand_block_isbad;
        mtd->block_markbad = nand_block_markbad;
+       mtd->writebufsize = mtd->writesize;
  
        /* propagate ecc.layout to mtd_info */
        mtd->ecclayout = chip->ecc.layout;
@@@ -35,6 -35,7 +35,7 @@@
  #include <linux/dma-mapping.h>
  #include <linux/io.h>
  #include <linux/slab.h>
+ #include <linux/regulator/consumer.h>
  
  #include <asm/mach/flash.h>
  #include <plat/gpmc.h>
@@@ -63,8 -64,13 +64,13 @@@ struct omap2_onenand 
        int dma_channel;
        int freq;
        int (*setup)(void __iomem *base, int freq);
+       struct regulator *regulator;
  };
  
+ #ifdef CONFIG_MTD_PARTITIONS
+ static const char *part_probes[] = { "cmdlinepart", NULL,  };
+ #endif
  static void omap2_onenand_dma_cb(int lch, u16 ch_status, void *data)
  {
        struct omap2_onenand *c = data;
@@@ -108,8 -114,9 +114,9 @@@ static void wait_warn(char *msg, int st
  static int omap2_onenand_wait(struct mtd_info *mtd, int state)
  {
        struct omap2_onenand *c = container_of(mtd, struct omap2_onenand, mtd);
+       struct onenand_chip *this = mtd->priv;
        unsigned int intr = 0;
-       unsigned int ctrl;
+       unsigned int ctrl, ctrl_mask;
        unsigned long timeout;
        u32 syscfg;
  
@@@ -180,7 -187,8 +187,8 @@@ retry
                        if (result == 0) {
                                /* Timeout after 20ms */
                                ctrl = read_reg(c, ONENAND_REG_CTRL_STATUS);
-                               if (ctrl & ONENAND_CTRL_ONGO) {
+                               if (ctrl & ONENAND_CTRL_ONGO &&
+                                   !this->ongoing) {
                                        /*
                                         * The operation seems to be still going
                                         * so give it some more time.
                return -EIO;
        }
  
-       if (ctrl & 0xFE9F)
+       ctrl_mask = 0xFE9F;
+       if (this->ongoing)
+               ctrl_mask &= ~0x8000;
+       if (ctrl & ctrl_mask)
                wait_warn("unexpected controller status", state, ctrl, intr);
  
        return 0;
@@@ -591,6 -603,30 +603,30 @@@ static void omap2_onenand_shutdown(stru
        memset((__force void *)c->onenand.base, 0, ONENAND_BUFRAM_SIZE);
  }
  
+ static int omap2_onenand_enable(struct mtd_info *mtd)
+ {
+       int ret;
+       struct omap2_onenand *c = container_of(mtd, struct omap2_onenand, mtd);
+       ret = regulator_enable(c->regulator);
+       if (ret != 0)
+               dev_err(&c->pdev->dev, "cant enable regulator\n");
+       return ret;
+ }
+ static int omap2_onenand_disable(struct mtd_info *mtd)
+ {
+       int ret;
+       struct omap2_onenand *c = container_of(mtd, struct omap2_onenand, mtd);
+       ret = regulator_disable(c->regulator);
+       if (ret != 0)
+               dev_err(&c->pdev->dev, "cant disable regulator\n");
+       return ret;
+ }
  static int __devinit omap2_onenand_probe(struct platform_device *pdev)
  {
        struct omap_onenand_platform_data *pdata;
                }
        }
  
+       if (pdata->regulator_can_sleep) {
+               c->regulator = regulator_get(&pdev->dev, "vonenand");
+               if (IS_ERR(c->regulator)) {
+                       dev_err(&pdev->dev,  "Failed to get regulator\n");
+                       goto err_release_dma;
+               }
+               c->onenand.enable = omap2_onenand_enable;
+               c->onenand.disable = omap2_onenand_disable;
+       }
        if ((r = onenand_scan(&c->mtd, 1)) < 0)
-               goto err_release_dma;
+               goto err_release_regulator;
  
        switch ((c->onenand.version_id >> 4) & 0xf) {
        case 0:
        case 3:
                c->freq = 83;
                break;
 +      case 4:
 +              c->freq = 104;
 +              break;
        }
  
  #ifdef CONFIG_MTD_PARTITIONS
-       if (pdata->parts != NULL)
-               r = add_mtd_partitions(&c->mtd, pdata->parts,
-                                      pdata->nr_parts);
+       r = parse_mtd_partitions(&c->mtd, part_probes, &c->parts, 0);
+       if (r > 0)
+               r = add_mtd_partitions(&c->mtd, c->parts, r);
+       else if (pdata->parts != NULL)
+               r = add_mtd_partitions(&c->mtd, pdata->parts, pdata->nr_parts);
        else
  #endif
                r = add_mtd_device(&c->mtd);
-       if (r < 0)
+       if (r)
                goto err_release_onenand;
  
        platform_set_drvdata(pdev, c);
  
  err_release_onenand:
        onenand_release(&c->mtd);
+ err_release_regulator:
+       regulator_put(c->regulator);
  err_release_dma:
        if (c->dma_channel != -1)
                omap_free_dma(c->dma_channel);
@@@ -757,6 -804,7 +807,7 @@@ err_release_mem_region
  err_free_cs:
        gpmc_cs_free(c->gpmc_cs);
  err_kfree:
+       kfree(c->parts);
        kfree(c);
  
        return r;
@@@ -766,18 -814,8 +817,8 @@@ static int __devexit omap2_onenand_remo
  {
        struct omap2_onenand *c = dev_get_drvdata(&pdev->dev);
  
-       BUG_ON(c == NULL);
- #ifdef CONFIG_MTD_PARTITIONS
-       if (c->parts)
-               del_mtd_partitions(&c->mtd);
-       else
-               del_mtd_device(&c->mtd);
- #else
-       del_mtd_device(&c->mtd);
- #endif
        onenand_release(&c->mtd);
+       regulator_put(c->regulator);
        if (c->dma_channel != -1)
                omap_free_dma(c->dma_channel);
        omap2_onenand_shutdown(pdev);
        iounmap(c->onenand.base);
        release_mem_region(c->phys_base, ONENAND_IO_SIZE);
        gpmc_cs_free(c->gpmc_cs);
+       kfree(c->parts);
        kfree(c);
  
        return 0;