]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ARM: omap2+: gpmc-nand: Use dynamic platform_device_alloc()
authorRostislav Lisovy <lisovy@gmail.com>
Wed, 4 Jun 2014 14:24:35 +0000 (16:24 +0200)
committerRoger Quadros <rogerq@ti.com>
Fri, 11 Jul 2014 13:15:13 +0000 (16:15 +0300)
GPMC controller supports up to 8 memory devices connected to it.
Since there is one statically allocated "struct platform_device
gpmc_nand_device" it is not possible to configure the system to
use more than one NAND device connected to the GPMC. This
modification makes it possible to use up to 8 NAND devices
connected to the GPMC controller.

Signed-off-by: Rostislav Lisovy <lisovy@merica.cz>
Signed-off-by: Roger Quadros <rogerq@ti.com>
arch/arm/mach-omap2/gpmc-nand.c

index 17cd39360afe853562b61a5dfb755f33ba5d7886..7ab486eeb769e80b9ef836c3793254eb5a0150ca 100644 (file)
 /* minimum size for IO mapping */
 #define        NAND_IO_SIZE    4
 
-static struct resource gpmc_nand_resource[] = {
-       {
-               .flags          = IORESOURCE_MEM,
-       },
-       {
-               .flags          = IORESOURCE_IRQ,
-       },
-       {
-               .flags          = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device gpmc_nand_device = {
-       .name           = "omap2-nand",
-       .id             = 0,
-       .num_resources  = ARRAY_SIZE(gpmc_nand_resource),
-       .resource       = gpmc_nand_resource,
-};
-
 static bool gpmc_hwecc_bch_capable(enum omap_ecc ecc_opt)
 {
        /* platforms which support all ECC schemes */
@@ -93,43 +74,41 @@ int gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data,
 {
        int err = 0;
        struct gpmc_settings s;
-       struct device *dev = &gpmc_nand_device.dev;
-
-       memset(&s, 0, sizeof(struct gpmc_settings));
+       struct platform_device *pdev;
+       struct resource gpmc_nand_res[] = {
+               { .flags = IORESOURCE_MEM, },
+               { .flags = IORESOURCE_IRQ, },
+               { .flags = IORESOURCE_IRQ, },
+       };
 
-       gpmc_nand_device.dev.platform_data = gpmc_nand_data;
+       BUG_ON(gpmc_nand_data->cs >= GPMC_CS_NUM);
 
        err = gpmc_cs_request(gpmc_nand_data->cs, NAND_IO_SIZE,
-                               (unsigned long *)&gpmc_nand_resource[0].start);
+                             (unsigned long *)&gpmc_nand_res[0].start);
        if (err < 0) {
-               dev_err(dev, "Cannot request GPMC CS %d, error %d\n",
-                       gpmc_nand_data->cs, err);
+               pr_err("omap2-gpmc: Cannot request GPMC CS %d, error %d\n",
+                      gpmc_nand_data->cs, err);
                return err;
        }
-
-       gpmc_nand_resource[0].end = gpmc_nand_resource[0].start +
-                                                       NAND_IO_SIZE - 1;
-
-       gpmc_nand_resource[1].start =
-                               gpmc_get_client_irq(GPMC_IRQ_FIFOEVENTENABLE);
-       gpmc_nand_resource[2].start =
-                               gpmc_get_client_irq(GPMC_IRQ_COUNT_EVENT);
+       gpmc_nand_res[0].end = gpmc_nand_res[0].start + NAND_IO_SIZE - 1;
+       gpmc_nand_res[1].start = gpmc_get_client_irq(GPMC_IRQ_FIFOEVENTENABLE);
+       gpmc_nand_res[2].start = gpmc_get_client_irq(GPMC_IRQ_COUNT_EVENT);
 
        if (gpmc_t) {
                err = gpmc_cs_set_timings(gpmc_nand_data->cs, gpmc_t);
                if (err < 0) {
-                       dev_err(dev, "Unable to set gpmc timings: %d\n", err);
+                       pr_err("omap2-gpmc: Unable to set gpmc timings: %d\n", err);
                        return err;
                }
        }
 
+       memset(&s, 0, sizeof(struct gpmc_settings));
        if (gpmc_nand_data->of_node)
                gpmc_read_settings_dt(gpmc_nand_data->of_node, &s);
        else
                gpmc_set_legacy(gpmc_nand_data, &s);
 
        s.device_nand = true;
-
        err = gpmc_cs_program_settings(gpmc_nand_data->cs, &s);
        if (err < 0)
                goto out_free_cs;
@@ -141,18 +120,34 @@ int gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data,
        gpmc_update_nand_reg(&gpmc_nand_data->reg, gpmc_nand_data->cs);
 
        if (!gpmc_hwecc_bch_capable(gpmc_nand_data->ecc_opt)) {
-               dev_err(dev, "Unsupported NAND ECC scheme selected\n");
-               return -EINVAL;
+               pr_err("omap2-nand: Unsupported NAND ECC scheme selected\n");
+               err = -EINVAL;
+               goto out_free_cs;
        }
 
-       err = platform_device_register(&gpmc_nand_device);
-       if (err < 0) {
-               dev_err(dev, "Unable to register NAND device\n");
-               goto out_free_cs;
+
+       pdev = platform_device_alloc("omap2-nand", gpmc_nand_data->cs);
+       if (pdev) {
+               err = platform_device_add_resources(pdev, gpmc_nand_res,
+                                                   ARRAY_SIZE(gpmc_nand_res));
+               if (!err)
+                       pdev->dev.platform_data = gpmc_nand_data;
+       } else {
+               err = -ENOMEM;
+       }
+       if (err)
+               goto out_free_pdev;
+
+       err = platform_device_add(pdev);
+       if (err) {
+               dev_err(&pdev->dev, "Unable to register NAND device\n");
+               goto out_free_pdev;
        }
 
        return 0;
 
+out_free_pdev:
+       platform_device_put(pdev);
 out_free_cs:
        gpmc_cs_free(gpmc_nand_data->cs);