]> Git Repo - linux.git/commitdiff
Merge tag 'for-linus-20140610' of git://git.infradead.org/linux-mtd
authorLinus Torvalds <[email protected]>
Wed, 11 Jun 2014 15:35:34 +0000 (08:35 -0700)
committerLinus Torvalds <[email protected]>
Wed, 11 Jun 2014 15:35:34 +0000 (08:35 -0700)
Pull MTD updates from Brian Norris:
 - refactor m25p80.c driver for use as a general SPI NOR framework for
   other drivers which may speak to SPI NOR flash without providing full
   SPI support (i.e., not part of drivers/spi/)
 - new Freescale QuadSPI driver (utilizing new SPI NOR framework)
 - updates for the STMicro "FSM" SPI NOR driver
 - fix sync/flush behavior on mtd_blkdevs
 - fixup subpage write support on a few NAND drivers
 - correct the MTD OOB test for odd-sized OOB areas
 - add BCH-16 support for OMAP NAND
 - fix warnings and trivial refactoring
 - utilize new ECC DT bindings in pxa3xx NAND driver
 - new LPDDR NVM driver
 - address a few assorted bugs caught by Coverity
 - add new imx6sx support for GPMI NAND
 - use a bounce buffer for NAND when non-DMA-able buffers are used

* tag 'for-linus-20140610' of git://git.infradead.org/linux-mtd: (77 commits)
  mtd: gpmi: add gpmi support for imx6sx
  mtd: maps: remove check for CONFIG_MTD_SUPERH_RESERVE
  mtd: bf5xx_nand: use the managed version of kzalloc
  mtd: pxa3xx_nand: make the driver work on big-endian systems
  mtd: nand: omap: fix omap_calculate_ecc_bch() for-loop error
  mtd: nand: r852: correct write_buf loop bounds
  mtd: nand_bbt: handle error case for nand_create_badblock_pattern()
  mtd: nand_bbt: remove unused variable
  mtd: maps: sc520cdp: fix warnings
  mtd: slram: fix unused variable warning
  mtd: pfow: remove unused variable
  mtd: lpddr: fix Kconfig dependency, for I/O accessors
  mtd: nand: pxa3xx: Add supported ECC strength and step size to the DT binding
  mtd: nand: pxa3xx: Use ECC strength and step size devicetree binding
  mtd: nand: pxa3xx: Clean pxa_ecc_init() error handling
  mtd: nand: Warn the user if the selected ECC strength is too weak
  mtd: nand: omap: Documentation: How to select correct ECC scheme for your device ?
  mtd: nand: omap: add support for BCH16_ECC - NAND driver updates
  mtd: nand: omap: add support for BCH16_ECC - ELM driver updates
  mtd: nand: omap: add support for BCH16_ECC - GPMC driver updates
  ...

1  2 
Documentation/devicetree/bindings/mtd/gpmc-nand.txt
arch/arm/mach-omap2/gpmc.c
drivers/mtd/mtd_blkdevs.c

index eb05255b6788e402035e32f11af4335307d756f6,eb81435ea15a3fe00e8e0edb4ea5c8784579d28d..65f4f7c43136a0507ddbb23a7dc511c94cc34cdb
@@@ -28,6 -28,8 +28,8 @@@ Optional properties
                "ham1"          1-bit Hamming ecc code
                "bch4"          4-bit BCH ecc code
                "bch8"          8-bit BCH ecc code
+               "bch16"         16-bit BCH ECC code
+               Refer below "How to select correct ECC scheme for your device ?"
  
   - ti,nand-xfer-type:         A string setting the data transfer type. One of:
  
@@@ -43,7 -45,7 +45,7 @@@
                ELM hardware engines should specify this device node in .dtsi
                Using ELM for ECC error correction frees some CPU cycles.
  
 -For inline partiton table parsing (optional):
 +For inline partition table parsing (optional):
  
   - #address-cells: should be set to 1
   - #size-cells: should be set to 1
@@@ -90,3 -92,46 +92,46 @@@ Example for an AM33xx board
                };
        };
  
+ How to select correct ECC scheme for your device ?
+ --------------------------------------------------
+ Higher ECC scheme usually means better protection against bit-flips and
+ increased system lifetime. However, selection of ECC scheme is dependent
+ on various other factors also like;
+ (1) support of built in hardware engines.
+       Some legacy OMAP SoC do not have ELM harware engine, so those SoC cannot
+       support ecc-schemes with hardware error-correction (BCHx_HW). However
+       such SoC can use ecc-schemes with software library for error-correction
+       (BCHx_HW_DETECTION_SW). The error correction capability with software
+       library remains equivalent to their hardware counter-part, but there is
+       slight CPU penalty when too many bit-flips are detected during reads.
+ (2) Device parameters like OOBSIZE.
+       Other factor which governs the selection of ecc-scheme is oob-size.
+       Higher ECC schemes require more OOB/Spare area to store ECC syndrome,
+       so the device should have enough free bytes available its OOB/Spare
+       area to accomodate ECC for entire page. In general following expression
+       helps in determining if given device can accomodate ECC syndrome:
+       "2 + (PAGESIZE / 512) * ECC_BYTES" >= OOBSIZE"
+       where
+               OOBSIZE         number of bytes in OOB/spare area
+               PAGESIZE        number of bytes in main-area of device page
+               ECC_BYTES       number of ECC bytes generated to protect
+                               512 bytes of data, which is:
+                               '3' for HAM1_xx ecc schemes
+                               '7' for BCH4_xx ecc schemes
+                               '14' for BCH8_xx ecc schemes
+                               '26' for BCH16_xx ecc schemes
+       Example(a): For a device with PAGESIZE = 2048 and OOBSIZE = 64 and
+               trying to use BCH16 (ECC_BYTES=26) ecc-scheme.
+               Number of ECC bytes per page = (2 + (2048 / 512) * 26) = 106 B
+               which is greater than capacity of NAND device (OOBSIZE=64)
+               Hence, BCH16 cannot be supported on given device. But it can
+               probably use lower ecc-schemes like BCH8.
+       Example(b): For a device with PAGESIZE = 2048 and OOBSIZE = 128 and
+               trying to use BCH16 (ECC_BYTES=26) ecc-scheme.
+               Number of ECC bytes per page = (2 + (2048 / 512) * 26) = 106 B
+               which can be accomodate in the OOB/Spare area of this device
+               (OOBSIZE=128). So this device can use BCH16 ecc-scheme.
index 852b19a367f06d74e549b7b674d057ee193b508c,9b27773db0405f1fb2d331f8ef95942bf60e0f99..2c0c2816900ffc3ae1e7b1a75b9db6f559399957
@@@ -68,6 -68,9 +68,9 @@@
  #define       GPMC_ECC_BCH_RESULT_1   0x244   /* not available on OMAP2 */
  #define       GPMC_ECC_BCH_RESULT_2   0x248   /* not available on OMAP2 */
  #define       GPMC_ECC_BCH_RESULT_3   0x24c   /* not available on OMAP2 */
+ #define       GPMC_ECC_BCH_RESULT_4   0x300   /* not available on OMAP2 */
+ #define       GPMC_ECC_BCH_RESULT_5   0x304   /* not available on OMAP2 */
+ #define       GPMC_ECC_BCH_RESULT_6   0x308   /* not available on OMAP2 */
  
  /* GPMC ECC control settings */
  #define GPMC_ECC_CTRL_ECCCLEAR                0x100
@@@ -170,12 -173,12 +173,12 @@@ static irqreturn_t gpmc_handle_irq(int 
  
  static void gpmc_write_reg(int idx, u32 val)
  {
 -      __raw_writel(val, gpmc_base + idx);
 +      writel_relaxed(val, gpmc_base + idx);
  }
  
  static u32 gpmc_read_reg(int idx)
  {
 -      return __raw_readl(gpmc_base + idx);
 +      return readl_relaxed(gpmc_base + idx);
  }
  
  void gpmc_cs_write_reg(int cs, int idx, u32 val)
        void __iomem *reg_addr;
  
        reg_addr = gpmc_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
 -      __raw_writel(val, reg_addr);
 +      writel_relaxed(val, reg_addr);
  }
  
  static u32 gpmc_cs_read_reg(int cs, int idx)
        void __iomem *reg_addr;
  
        reg_addr = gpmc_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
 -      return __raw_readl(reg_addr);
 +      return readl_relaxed(reg_addr);
  }
  
  /* TODO: Add support for gpmc_fck to clock framework and use it */
@@@ -501,7 -504,7 +504,7 @@@ static int gpmc_cs_delete_mem(int cs
        int r;
  
        spin_lock(&gpmc_mem_lock);
 -      r = release_resource(&gpmc_cs_mem[cs]);
 +      r = release_resource(res);
        res->start = 0;
        res->end = 0;
        spin_unlock(&gpmc_mem_lock);
@@@ -527,14 -530,6 +530,14 @@@ static int gpmc_cs_remap(int cs, u32 ba
                pr_err("%s: requested chip-select is disabled\n", __func__);
                return -ENODEV;
        }
 +
 +      /*
 +       * Make sure we ignore any device offsets from the GPMC partition
 +       * allocated for the chip select and that the new base confirms
 +       * to the GPMC 16MB minimum granularity.
 +       */ 
 +      base &= ~(SZ_16M - 1);
 +
        gpmc_cs_get_memconf(cs, &old_base, &size);
        if (base == old_base)
                return 0;
@@@ -594,8 -589,6 +597,8 @@@ EXPORT_SYMBOL(gpmc_cs_request)
  
  void gpmc_cs_free(int cs)
  {
 +      struct resource *res = &gpmc_cs_mem[cs];
 +
        spin_lock(&gpmc_mem_lock);
        if (cs >= gpmc_cs_num || cs < 0 || !gpmc_cs_reserved(cs)) {
                printk(KERN_ERR "Trying to free non-reserved GPMC CS%d\n", cs);
                return;
        }
        gpmc_cs_disable_mem(cs);
 -      release_resource(&gpmc_cs_mem[cs]);
 +      if (res->flags)
 +              release_resource(res);
        gpmc_cs_set_reserved(cs, 0);
        spin_unlock(&gpmc_mem_lock);
  }
@@@ -677,6 -669,12 +680,12 @@@ void gpmc_update_nand_reg(struct gpmc_n
                                           GPMC_BCH_SIZE * i;
                reg->gpmc_bch_result3[i] = gpmc_base + GPMC_ECC_BCH_RESULT_3 +
                                           GPMC_BCH_SIZE * i;
+               reg->gpmc_bch_result4[i] = gpmc_base + GPMC_ECC_BCH_RESULT_4 +
+                                          i * GPMC_BCH_SIZE;
+               reg->gpmc_bch_result5[i] = gpmc_base + GPMC_ECC_BCH_RESULT_5 +
+                                          i * GPMC_BCH_SIZE;
+               reg->gpmc_bch_result6[i] = gpmc_base + GPMC_ECC_BCH_RESULT_6 +
+                                          i * GPMC_BCH_SIZE;
        }
  }
  
@@@ -1412,6 -1410,12 +1421,12 @@@ static int gpmc_probe_nand_child(struc
                else
                        gpmc_nand_data->ecc_opt =
                                OMAP_ECC_BCH8_CODE_HW_DETECTION_SW;
+       else if (!strcmp(s, "bch16"))
+               if (gpmc_nand_data->elm_of_node)
+                       gpmc_nand_data->ecc_opt =
+                               OMAP_ECC_BCH16_CODE_HW;
+               else
+                       pr_err("%s: BCH16 requires ELM support\n", __func__);
        else
                pr_err("%s: ti,nand-ecc-opt invalid value\n", __func__);
  
index 4dbfaee9aa9583c41508b27a0e993480a265ebc2,d2f0da91a5bd552371abe266843bdb9562181aa2..43e30992a3697a76f932bc778c76d8bcdf7080ce
@@@ -82,11 -82,15 +82,14 @@@ static int do_blktrans_request(struct m
  
        block = blk_rq_pos(req) << 9 >> tr->blkshift;
        nsect = blk_rq_cur_bytes(req) >> tr->blkshift;
 -
 -      buf = req->buffer;
 +      buf = bio_data(req->bio);
  
        if (req->cmd_type != REQ_TYPE_FS)
                return -EIO;
  
+       if (req->cmd_flags & REQ_FLUSH)
+               return tr->flush(dev);
        if (blk_rq_pos(req) + blk_rq_cur_sectors(req) >
            get_capacity(req->rq_disk))
                return -EIO;
@@@ -407,6 -411,9 +410,9 @@@ int add_mtd_blktrans_dev(struct mtd_blk
        if (!new->rq)
                goto error3;
  
+       if (tr->flush)
+               blk_queue_flush(new->rq, REQ_FLUSH);
        new->rq->queuedata = new;
        blk_queue_logical_block_size(new->rq, tr->blksize);
  
This page took 0.091357 seconds and 4 git commands to generate.