1/* 2 * NAND Flash Controller Device Driver 3 * Copyright © 2009-2010, Intel Corporation and its suppliers. 4 * 5 * This program is free software; you can redistribute it and/or modify it 6 * under the terms and conditions of the GNU General Public License, 7 * version 2, as published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12 * more details. 13 */ 14#include <linux/kernel.h> 15#include <linux/module.h> 16#include <linux/pci.h> 17#include <linux/slab.h> 18 19#include "denali.h" 20 21#define DENALI_NAND_NAME "denali-nand-pci" 22 23/* List of platforms this NAND controller has be integrated into */ 24static const struct pci_device_id denali_pci_ids[] = { 25 { PCI_VDEVICE(INTEL, 0x0701), INTEL_CE4100 }, 26 { PCI_VDEVICE(INTEL, 0x0809), INTEL_MRST }, 27 { /* end: all zeroes */ } 28}; 29MODULE_DEVICE_TABLE(pci, denali_pci_ids); 30 31static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) 32{ 33 int ret = -ENODEV; 34 resource_size_t csr_base, mem_base; 35 unsigned long csr_len, mem_len; 36 struct denali_nand_info *denali; 37 38 denali = kzalloc(sizeof(*denali), GFP_KERNEL); 39 if (!denali) 40 return -ENOMEM; 41 42 ret = pci_enable_device(dev); 43 if (ret) { 44 pr_err("Spectra: pci_enable_device failed.\n"); 45 goto failed_alloc_memery; 46 } 47 48 if (id->driver_data == INTEL_CE4100) { 49 denali->platform = INTEL_CE4100; 50 mem_base = pci_resource_start(dev, 0); 51 mem_len = pci_resource_len(dev, 1); 52 csr_base = pci_resource_start(dev, 1); 53 csr_len = pci_resource_len(dev, 1); 54 } else { 55 denali->platform = INTEL_MRST; 56 csr_base = pci_resource_start(dev, 0); 57 csr_len = pci_resource_len(dev, 0); 58 mem_base = pci_resource_start(dev, 1); 59 mem_len = pci_resource_len(dev, 1); 60 if (!mem_len) { 61 mem_base = csr_base + csr_len; 62 mem_len = csr_len; 63 } 64 } 65 66 pci_set_master(dev); 67 denali->dev = &dev->dev; 68 denali->irq = dev->irq; 69 70 ret = pci_request_regions(dev, DENALI_NAND_NAME); 71 if (ret) { 72 pr_err("Spectra: Unable to request memory regions\n"); 73 goto failed_enable_dev; 74 } 75 76 denali->flash_reg = ioremap_nocache(csr_base, csr_len); 77 if (!denali->flash_reg) { 78 pr_err("Spectra: Unable to remap memory region\n"); 79 ret = -ENOMEM; 80 goto failed_req_regions; 81 } 82 83 denali->flash_mem = ioremap_nocache(mem_base, mem_len); 84 if (!denali->flash_mem) { 85 pr_err("Spectra: ioremap_nocache failed!"); 86 ret = -ENOMEM; 87 goto failed_remap_reg; 88 } 89 90 ret = denali_init(denali); 91 if (ret) 92 goto failed_remap_mem; 93 94 pci_set_drvdata(dev, denali); 95 96 return 0; 97 98failed_remap_mem: 99 iounmap(denali->flash_mem); 100failed_remap_reg: 101 iounmap(denali->flash_reg); 102failed_req_regions: 103 pci_release_regions(dev); 104failed_enable_dev: 105 pci_disable_device(dev); 106failed_alloc_memery: 107 kfree(denali); 108 109 return ret; 110} 111 112/* driver exit point */ 113static void denali_pci_remove(struct pci_dev *dev) 114{ 115 struct denali_nand_info *denali = pci_get_drvdata(dev); 116 117 denali_remove(denali); 118 iounmap(denali->flash_reg); 119 iounmap(denali->flash_mem); 120 pci_release_regions(dev); 121 pci_disable_device(dev); 122 kfree(denali); 123} 124 125static struct pci_driver denali_pci_driver = { 126 .name = DENALI_NAND_NAME, 127 .id_table = denali_pci_ids, 128 .probe = denali_pci_probe, 129 .remove = denali_pci_remove, 130}; 131 132static int denali_init_pci(void) 133{ 134 return pci_register_driver(&denali_pci_driver); 135} 136module_init(denali_init_pci); 137 138static void denali_exit_pci(void) 139{ 140 pci_unregister_driver(&denali_pci_driver); 141} 142module_exit(denali_exit_pci); 143