mtd: nand: omap: Synchronize the access to the ECC engine
authorRostislav Lisovy <lisovy@gmail.com>
Wed, 29 Oct 2014 10:10:59 +0000 (11:10 +0100)
committerBrian Norris <computersforpeace@gmail.com>
Wed, 5 Nov 2014 21:01:22 +0000 (13:01 -0800)
The AM335x Technical Reference Manual (spruh73j.pdf) says
"Because the ECC engine includes only one accumulation context,
it can be allocated to only one chip-select at a time ... "
(7.1.3.3.12.3). Since the commit 97a288ba2cfa ("ARM: omap2+:
gpmc-nand: Use dynamic platform_device_alloc()") gpmc-nand
driver supports multiple NAND flash devices connected to
the single controller.
Use global 'struct nand_hw_control' among multiple NAND
instances to synchronize the access to the single ECC Engine.

Tested with custom AM335x board using 2x NAND flash chips.

Signed-off-by: Rostislav Lisovy <lisovy@merica.cz>
Acked-by: Roger Quadros <rogerq@ti.com>
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
drivers/mtd/nand/omap2.c

index b0f89d87de89594777121fbc81fc545e361c3a48..1ec0a1dbed3db0e1a0a87387f19e4f7565148c86 100644 (file)
@@ -144,8 +144,13 @@ static u_char bch8_vector[] = {0xf3, 0xdb, 0x14, 0x16, 0x8b, 0xd2, 0xbe, 0xcc,
        0xac, 0x6b, 0xff, 0x99, 0x7b};
 static u_char bch4_vector[] = {0x00, 0x6b, 0x31, 0xdd, 0x41, 0xbc, 0x10};
 
+/* Shared among all NAND instances to synchronize access to the ECC Engine */
+static struct nand_hw_control omap_gpmc_controller = {
+       .lock = __SPIN_LOCK_UNLOCKED(omap_gpmc_controller.lock),
+       .wq = __WAIT_QUEUE_HEAD_INITIALIZER(omap_gpmc_controller.wq),
+};
+
 struct omap_nand_info {
-       struct nand_hw_control          controller;
        struct omap_nand_platform_data  *pdata;
        struct mtd_info                 mtd;
        struct nand_chip                nand;
@@ -1685,9 +1690,6 @@ static int omap_nand_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, info);
 
-       spin_lock_init(&info->controller.lock);
-       init_waitqueue_head(&info->controller.wq);
-
        info->pdev              = pdev;
        info->gpmc_cs           = pdata->cs;
        info->reg               = pdata->reg;
@@ -1707,7 +1709,7 @@ static int omap_nand_probe(struct platform_device *pdev)
 
        info->phys_base = res->start;
 
-       nand_chip->controller = &info->controller;
+       nand_chip->controller = &omap_gpmc_controller;
 
        nand_chip->IO_ADDR_W = nand_chip->IO_ADDR_R;
        nand_chip->cmd_ctrl  = omap_hwcontrol;