root/drivers/mtd/nand/raw/plat_nand.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. plat_nand_probe
  2. plat_nand_remove

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Generic NAND driver
   4  *
   5  * Author: Vitaly Wool <vitalywool@gmail.com>
   6  */
   7 
   8 #include <linux/err.h>
   9 #include <linux/io.h>
  10 #include <linux/module.h>
  11 #include <linux/platform_device.h>
  12 #include <linux/slab.h>
  13 #include <linux/mtd/mtd.h>
  14 #include <linux/mtd/platnand.h>
  15 
  16 struct plat_nand_data {
  17         struct nand_chip        chip;
  18         void __iomem            *io_base;
  19 };
  20 
  21 /*
  22  * Probe for the NAND device.
  23  */
  24 static int plat_nand_probe(struct platform_device *pdev)
  25 {
  26         struct platform_nand_data *pdata = dev_get_platdata(&pdev->dev);
  27         struct plat_nand_data *data;
  28         struct mtd_info *mtd;
  29         struct resource *res;
  30         const char **part_types;
  31         int err = 0;
  32 
  33         if (!pdata) {
  34                 dev_err(&pdev->dev, "platform_nand_data is missing\n");
  35                 return -EINVAL;
  36         }
  37 
  38         if (pdata->chip.nr_chips < 1) {
  39                 dev_err(&pdev->dev, "invalid number of chips specified\n");
  40                 return -EINVAL;
  41         }
  42 
  43         /* Allocate memory for the device structure (and zero it) */
  44         data = devm_kzalloc(&pdev->dev, sizeof(struct plat_nand_data),
  45                             GFP_KERNEL);
  46         if (!data)
  47                 return -ENOMEM;
  48 
  49         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  50         data->io_base = devm_ioremap_resource(&pdev->dev, res);
  51         if (IS_ERR(data->io_base))
  52                 return PTR_ERR(data->io_base);
  53 
  54         nand_set_flash_node(&data->chip, pdev->dev.of_node);
  55         mtd = nand_to_mtd(&data->chip);
  56         mtd->dev.parent = &pdev->dev;
  57 
  58         data->chip.legacy.IO_ADDR_R = data->io_base;
  59         data->chip.legacy.IO_ADDR_W = data->io_base;
  60         data->chip.legacy.cmd_ctrl = pdata->ctrl.cmd_ctrl;
  61         data->chip.legacy.dev_ready = pdata->ctrl.dev_ready;
  62         data->chip.legacy.select_chip = pdata->ctrl.select_chip;
  63         data->chip.legacy.write_buf = pdata->ctrl.write_buf;
  64         data->chip.legacy.read_buf = pdata->ctrl.read_buf;
  65         data->chip.legacy.chip_delay = pdata->chip.chip_delay;
  66         data->chip.options |= pdata->chip.options;
  67         data->chip.bbt_options |= pdata->chip.bbt_options;
  68 
  69         data->chip.ecc.mode = NAND_ECC_SOFT;
  70         data->chip.ecc.algo = NAND_ECC_HAMMING;
  71 
  72         platform_set_drvdata(pdev, data);
  73 
  74         /* Handle any platform specific setup */
  75         if (pdata->ctrl.probe) {
  76                 err = pdata->ctrl.probe(pdev);
  77                 if (err)
  78                         goto out;
  79         }
  80 
  81         /* Scan to find existence of the device */
  82         err = nand_scan(&data->chip, pdata->chip.nr_chips);
  83         if (err)
  84                 goto out;
  85 
  86         part_types = pdata->chip.part_probe_types;
  87 
  88         err = mtd_device_parse_register(mtd, part_types, NULL,
  89                                         pdata->chip.partitions,
  90                                         pdata->chip.nr_partitions);
  91 
  92         if (!err)
  93                 return err;
  94 
  95         nand_release(&data->chip);
  96 out:
  97         if (pdata->ctrl.remove)
  98                 pdata->ctrl.remove(pdev);
  99         return err;
 100 }
 101 
 102 /*
 103  * Remove a NAND device.
 104  */
 105 static int plat_nand_remove(struct platform_device *pdev)
 106 {
 107         struct plat_nand_data *data = platform_get_drvdata(pdev);
 108         struct platform_nand_data *pdata = dev_get_platdata(&pdev->dev);
 109 
 110         nand_release(&data->chip);
 111         if (pdata->ctrl.remove)
 112                 pdata->ctrl.remove(pdev);
 113 
 114         return 0;
 115 }
 116 
 117 static const struct of_device_id plat_nand_match[] = {
 118         { .compatible = "gen_nand" },
 119         {},
 120 };
 121 MODULE_DEVICE_TABLE(of, plat_nand_match);
 122 
 123 static struct platform_driver plat_nand_driver = {
 124         .probe  = plat_nand_probe,
 125         .remove = plat_nand_remove,
 126         .driver = {
 127                 .name           = "gen_nand",
 128                 .of_match_table = plat_nand_match,
 129         },
 130 };
 131 
 132 module_platform_driver(plat_nand_driver);
 133 
 134 MODULE_LICENSE("GPL");
 135 MODULE_AUTHOR("Vitaly Wool");
 136 MODULE_DESCRIPTION("Simple generic NAND driver");
 137 MODULE_ALIAS("platform:gen_nand");

/* [<][>][^][v][top][bottom][index][help] */