Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * NAND Flash Controller Device Driver
0004  * Copyright © 2009-2010, Intel Corporation and its suppliers.
0005  */
0006 
0007 #include <linux/errno.h>
0008 #include <linux/io.h>
0009 #include <linux/kernel.h>
0010 #include <linux/module.h>
0011 #include <linux/pci.h>
0012 
0013 #include "denali.h"
0014 
0015 #define DENALI_NAND_NAME    "denali-nand-pci"
0016 
0017 #define INTEL_CE4100    1
0018 #define INTEL_MRST  2
0019 
0020 /* List of platforms this NAND controller has be integrated into */
0021 static const struct pci_device_id denali_pci_ids[] = {
0022     { PCI_VDEVICE(INTEL, 0x0701), INTEL_CE4100 },
0023     { PCI_VDEVICE(INTEL, 0x0809), INTEL_MRST },
0024     { /* end: all zeroes */ }
0025 };
0026 MODULE_DEVICE_TABLE(pci, denali_pci_ids);
0027 
0028 NAND_ECC_CAPS_SINGLE(denali_pci_ecc_caps, denali_calc_ecc_bytes, 512, 8, 15);
0029 
0030 static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
0031 {
0032     resource_size_t csr_base, mem_base;
0033     unsigned long csr_len, mem_len;
0034     struct denali_controller *denali;
0035     struct denali_chip *dchip;
0036     int nsels, ret, i;
0037 
0038     denali = devm_kzalloc(&dev->dev, sizeof(*denali), GFP_KERNEL);
0039     if (!denali)
0040         return -ENOMEM;
0041 
0042     ret = pcim_enable_device(dev);
0043     if (ret) {
0044         dev_err(&dev->dev, "Spectra: pci_enable_device failed.\n");
0045         return ret;
0046     }
0047 
0048     if (id->driver_data == INTEL_CE4100) {
0049         mem_base = pci_resource_start(dev, 0);
0050         mem_len = pci_resource_len(dev, 1);
0051         csr_base = pci_resource_start(dev, 1);
0052         csr_len = pci_resource_len(dev, 1);
0053     } else {
0054         csr_base = pci_resource_start(dev, 0);
0055         csr_len = pci_resource_len(dev, 0);
0056         mem_base = pci_resource_start(dev, 1);
0057         mem_len = pci_resource_len(dev, 1);
0058         if (!mem_len) {
0059             mem_base = csr_base + csr_len;
0060             mem_len = csr_len;
0061         }
0062     }
0063 
0064     pci_set_master(dev);
0065     denali->dev = &dev->dev;
0066     denali->irq = dev->irq;
0067     denali->ecc_caps = &denali_pci_ecc_caps;
0068     denali->clk_rate = 50000000;        /* 50 MHz */
0069     denali->clk_x_rate = 200000000;     /* 200 MHz */
0070 
0071     ret = pci_request_regions(dev, DENALI_NAND_NAME);
0072     if (ret) {
0073         dev_err(&dev->dev, "Spectra: Unable to request memory regions\n");
0074         return ret;
0075     }
0076 
0077     denali->reg = devm_ioremap(denali->dev, csr_base, csr_len);
0078     if (!denali->reg) {
0079         dev_err(&dev->dev, "Spectra: Unable to remap memory region\n");
0080         return -ENOMEM;
0081     }
0082 
0083     denali->host = devm_ioremap(denali->dev, mem_base, mem_len);
0084     if (!denali->host) {
0085         dev_err(&dev->dev, "Spectra: ioremap failed!");
0086         return -ENOMEM;
0087     }
0088 
0089     ret = denali_init(denali);
0090     if (ret)
0091         return ret;
0092 
0093     nsels = denali->nbanks;
0094 
0095     dchip = devm_kzalloc(denali->dev, struct_size(dchip, sels, nsels),
0096                  GFP_KERNEL);
0097     if (!dchip) {
0098         ret = -ENOMEM;
0099         goto out_remove_denali;
0100     }
0101 
0102     dchip->chip.base.ecc.user_conf.flags |= NAND_ECC_MAXIMIZE_STRENGTH;
0103 
0104     dchip->nsels = nsels;
0105 
0106     for (i = 0; i < nsels; i++)
0107         dchip->sels[i].bank = i;
0108 
0109     ret = denali_chip_init(denali, dchip);
0110     if (ret)
0111         goto out_remove_denali;
0112 
0113     pci_set_drvdata(dev, denali);
0114 
0115     return 0;
0116 
0117 out_remove_denali:
0118     denali_remove(denali);
0119     return ret;
0120 }
0121 
0122 static void denali_pci_remove(struct pci_dev *dev)
0123 {
0124     struct denali_controller *denali = pci_get_drvdata(dev);
0125 
0126     denali_remove(denali);
0127 }
0128 
0129 static struct pci_driver denali_pci_driver = {
0130     .name = DENALI_NAND_NAME,
0131     .id_table = denali_pci_ids,
0132     .probe = denali_pci_probe,
0133     .remove = denali_pci_remove,
0134 };
0135 module_pci_driver(denali_pci_driver);
0136 
0137 MODULE_DESCRIPTION("PCI driver for Denali NAND controller");
0138 MODULE_AUTHOR("Intel Corporation and its suppliers");
0139 MODULE_LICENSE("GPL v2");